﻿Imports Commander_Wars.Spieletools
Imports Microsoft.DirectX.Direct3D
Imports Microsoft.DirectX
''' <summary>
''' Stellt algorhytmische Berechnungen an und zieht die Einheiten des Spielers
''' </summary>
''' <remarks></remarks>
Public MustInherit Class ObjektKI
#Region "Variablen"
    ''' <summary>
    ''' Wenn wir soweit fortgeschritten sind bringen uns Infantrie Transporter auch zu Feinden.
    ''' Ansonsten nur zu Besetzungen
    ''' </summary>
    ''' <remarks></remarks>
    Enum KIModiIntern
        ''' <summary>
        ''' Die KI wird gestartet
        ''' </summary>
        ''' <remarks></remarks>
        KIStart
        ''' <summary>
        ''' Die KI wartet und schaut ob sie eine Gabe einsetzen kann
        ''' </summary>
        ''' <remarks></remarks>
        StartWarten
        ''' <summary>
        ''' Die KI greift mit ihren Gebaeuden an
        ''' </summary>
        ''' <remarks></remarks>
        GebaeudeAngriff
        ''' <summary>
        ''' Die KI zieht die Hoelliums
        ''' </summary>
        ''' <remarks></remarks>
        HoelliumZiehen
        ''' <summary>
        ''' Die KI besetzt Gebaeude
        ''' </summary>
        ''' <remarks></remarks>
        Besetzen
        ''' <summary>
        ''' Die KI setzt ihre Fernwaffen ein
        ''' </summary>
        ''' <remarks></remarks>
        Fernkampf
        ''' <summary>
        ''' Die KI setzt ihre Panzer ein
        ''' </summary>
        ''' <remarks></remarks>
        Nahkampf
        ''' <summary>
        ''' Die KI zieht die Infanteristen
        ''' </summary>
        ''' <remarks></remarks>
        Infanterieziehen
        ''' <summary>
        ''' Die KI zieht ihre Panzer
        ''' </summary>
        ''' <remarks></remarks>
        Nahkampfziehen
        ''' <summary>
        ''' Die KI zieht die Fernwaffen
        ''' </summary>
        ''' <remarks></remarks>
        Fernkampfziehen
        ''' <summary>
        ''' Hier werden Truppen gezogen, die wenige Leben, Treibstoff oder Munition haben.
        ''' </summary>
        ''' <remarks></remarks>
        Rueckzug
        ''' <summary>
        ''' Transporter ohne Ladung verteilen Ration
        ''' </summary>
        ''' <remarks></remarks>
        Ration
        ''' <summary>
        ''' Hier werden Einheiten vereint
        ''' </summary>
        ''' <remarks></remarks>
        Einen
        ''' <summary>
        ''' Die Einheiten werden verladen
        ''' </summary>
        ''' <remarks></remarks>
        TransporterVerladen
        ''' <summary>
        ''' Die KI zieht die Transporter
        ''' </summary>
        ''' <remarks></remarks>
        Transproterziehen
        ''' <summary>
        ''' Steuert die Einheiten, welche ohne Berechnungen aus kommen
        ''' </summary>
        ''' <remarks></remarks>
        ExternGesteuerteEinheiten
        ''' <summary>
        ''' Die KI baut neue Truppen
        ''' </summary>
        ''' <remarks></remarks>
        Bauen
        ''' <summary>
        ''' Die KI setzt ihre Gabe fuer das Rundenende ein.
        ''' </summary>
        ''' <remarks></remarks>
        RundenEndeGabeEinsetzen
        ''' <summary>
        ''' Die KI beeendet ihren Zug
        ''' </summary>
        ''' <remarks></remarks>
        RundenEnde
    End Enum
    Enum KIModiExtern
        'ab hier stehen Einheiten Befehle
        ''' <summary>
        ''' Wir machen nichts
        ''' </summary>
        ''' <remarks></remarks>
        Keiner
        ''' <summary>
        ''' Wir wollen mit der Einheit warten
        ''' </summary>
        ''' <remarks></remarks>
        Warten
        ''' <summary>
        ''' Die Einheit soll besetzen
        ''' </summary>
        ''' <remarks></remarks>
        Besetzen
        ''' <summary>
        ''' We do an Instant Battle forced by Julia
        ''' </summary>
        ''' <remarks></remarks>
        InstantBattle
        ''' <summary>
        ''' Die Einheit soll Angreifen
        ''' </summary>
        ''' <remarks></remarks>
        Angriff
        ''' <summary>
        ''' Die Einheit soll Ration verteilen
        ''' </summary>
        ''' <remarks></remarks>
        Ration
        ''' <summary>
        ''' Die Einheit soll als Fracht aufgenommen werden
        ''' </summary>
        ''' <remarks></remarks>
        Fracht
        ''' <summary>
        ''' Die KI will zwei Einheiten einen
        ''' </summary>
        ''' <remarks></remarks>
        Einen
        ''' <summary>
        ''' Die KI repariert eine andere Einheit
        ''' </summary>
        ''' <remarks></remarks>
        Reparieren
        ''' <summary>
        ''' Die Einheit tarnt sich.
        ''' </summary>
        ''' <remarks></remarks>
        Tarnen
        ''' <summary>
        ''' Die Einheit taucht auf.
        ''' </summary>
        ''' <remarks></remarks>
        Auftauchen
        ''' <summary>
        ''' Eine S-Bombe explodiert
        ''' </summary>
        ''' <remarks></remarks>
        Explosion
        ''' <summary>
        ''' Feuert ein Silo auf ein Ziel ab.
        ''' </summary>
        ''' <remarks></remarks>
        SiloZuenden
        ''' <summary>
        ''' Entlaedt die Einheit auf ein Feld. 
        ''' AngreiferSchaden ist die wie vielte Einheit entladen wird.
        ''' </summary>
        ''' <remarks></remarks>
        Entladen
        ''' <summary>
        ''' Baut ein Gebaeude
        ''' </summary>
        ''' <remarks></remarks>
        GebaeudeBauen
        ''' <summary>
        ''' Schickt die Einheit auf die andere Schlacht
        ''' </summary>
        ''' <remarks></remarks>
        EinheitSchicken
        ''' <summary>
        ''' Baut eine Einheit in einem Flugzeugtraeger
        ''' </summary>
        ''' <remarks></remarks>
        FlugzeugtraegerBau
        ''' <summary>
        ''' Baut eine Temporaere Basis
        ''' </summary>
        ''' <remarks></remarks>
        TemporaereBasisbauen
        ''' <summary>
        ''' Laesst eine Einheit eine Leuchtrakete Abfeuern
        ''' </summary>
        ''' <remarks></remarks>
        Leuchtrakete
        ''' <summary>
        ''' Macht die Einheit zur KO Einheit
        ''' </summary>
        ''' <remarks></remarks>
        CreateKOEinheit
        'ab hier stehen Gebaeude befehle
        ''' <summary>
        ''' Sorgt dafuer das diese Einheit gebaut wird.
        ''' </summary>
        ''' <remarks></remarks>
        EinheitBauen
        ''' <summary>
        ''' Laesst ein Gebaeude feuern Opfer ist dabei unser Ziel.
        ''' </summary>
        ''' <remarks></remarks>
        Schuss
        ''' <summary>
        ''' Baut eine Einheit mit der Fabrik.
        ''' </summary>
        ''' <remarks></remarks>
        FabrikBauen
        ''' <summary>
        ''' Startet die Omega-Rakete auf ein Ziel
        ''' </summary>
        ''' <remarks></remarks>
        OmegaRaketeStarten
        ''' <summary>
        ''' Kauft eine erweiterug der OmegaRakete
        ''' </summary>
        ''' <remarks></remarks>
        OmegaUpgradeKaufen
        'ab hier stehen Sonstige Befehle
        ''' <summary>
        ''' Beendet die Runde der KO bleibt am Zug
        ''' </summary>
        ''' <remarks></remarks>
        RundenEnde
        ''' <summary>
        ''' Beendet die Runde der KO wechselt evtl. Nochmaliges Ziehen durch Doppelgabe..
        ''' </summary>
        ''' <remarks></remarks>
        Wechsel
        ''' <summary>
        ''' Setzt die Gabe ein
        ''' </summary>
        ''' <remarks></remarks>
        GabeEinsetzen
        ''' <summary>
        ''' Setzt die Spezialgabe ein.
        ''' </summary>
        ''' <remarks></remarks>
        SpezialgabeEinsetzen
        ''' <summary>
        ''' Setzt die Doppelgabe ein
        ''' </summary>
        ''' <remarks></remarks>
        DoppelGabeEinsetzen
        ''' <summary>
        ''' Wir wollen das Schlachtfeld wechseln
        ''' </summary>
        ''' <remarks></remarks>
        Schlachtwechseln

        ''' <summary>
        ''' Wir wollen das Wetter veraendern. Nur KI Passiv Befehl
        ''' </summary>
        ''' <remarks></remarks>
        WetterWechsel
        ''' <summary>
        ''' Bewegt eine Wolke in der Luftschlacht. Nur KI Passiv Befehl
        ''' </summary>
        ''' <remarks></remarks>
        WolkeBewegen
        ''' <summary>
        ''' Verbessert eine Einheit. Nur KI Passiv Befehl
        ''' </summary>
        ''' <remarks></remarks>
        EinheitVerbessern
        ''' <summary>
        ''' Setzt den Treibstoff einer Einheit. Nur KI Passiv Befehl.
        ''' </summary>
        ''' <remarks></remarks>
        EinheitTreibstoffSetzen
        ''' <summary>
        ''' Laesst einen Vulkan Feuern. Nur KI Passiv Befehl
        ''' </summary>
        ''' <remarks></remarks>
        VulkanFeuer
        ''' <summary>
        ''' Forces a Unit to have moved already.
        ''' </summary>
        ''' <remarks></remarks>
        ShockUnit
        ''' <summary>
        ''' Places a Building for a Player at a specific Location
        ''' </summary>
        ''' <remarks></remarks>
        PlaceBuilding
        ''' <summary>
        ''' Changes the Owner of a Building
        ''' </summary>
        ''' <remarks></remarks>
        GetEnemyBuilding
        ''' <summary>
        ''' Launches a Rocket or similar Stuff at a Enemy Position.
        ''' Fascinating
        ''' </summary>
        ''' <remarks></remarks>
        LaunchRocket
        ''' <summary>
        ''' Hey we get a new Unit for free.
        ''' </summary>
        ''' <remarks></remarks>
        InvasionUnit
    End Enum
    Enum Besetzungsprioritaeten
        Keine
        FlughafebBasisHafenLaborHQStadt
        MeisteEinheiten
    End Enum
    Enum BeschussArten
        FernkampfFeindBoden
        NahkampfFeindBoden
        Geschuetzfeind
        eigeneFernkampf
        eigeneNahkampf
        HeilungEigene
        FernkampfFeindLuft
        NahkampfFeindLuft
    End Enum
    Enum GeldTPAngriffsModus
        NurGeld
        NurTP
        Beides
    End Enum
    Enum GebaeudeSortierKriterien
        Zufall
        ''' <summary>
        ''' Wir sortieren die Gebaeude nach ihrer Entfernung zum Feind.
        ''' </summary>
        ''' <remarks></remarks>
        NaehestenZumFeind
    End Enum
    Enum EinheitenSortierKriterien
        Zufall
        GroessterBewegungsradius
        Preis
        KleinsterBewegungsradius
    End Enum
    ''' <summary>
    ''' Solange True macht die KI nichts
    ''' </summary>
    ''' <remarks></remarks>
    Public KIKonsolenPause As Boolean = False
    ''' <summary>
    ''' Gibt an wie die KI berechnet welche Einheiten lohnende Opfer sind.
    ''' </summary>
    ''' <remarks></remarks>
    Protected OpferBerechnung As GeldTPAngriffsModus
    ''' <summary>
    ''' Fuehrt die Schleife aus.
    ''' </summary>
    ''' <remarks></remarks>
    Public KIThreat As Threading.Thread
    '''<summary>
    ''' Alle Einheiten die dieser Spieler kontrolliert
    ''' </summary>
    ''' <remarks></remarks>
    Protected Einheiten() As ObjektEinheit = {}
    ''' <summary>
    ''' Stellt das Spielfeld dar und zeigt an welche Landschaften der Spieler sehen kann
    ''' </summary>
    ''' <remarks></remarks>
    Public Sichtfeld(,,) As Boolean = {}
    ''' <summary>
    ''' Stellt alle Gebaeude die dieser Spieler zu beginn der Runde beseitzt dar.
    ''' </summary>
    ''' <remarks></remarks>
    Protected Gebaeude() As ObjektGebaeude = {}
    ''' <summary>
    ''' Der Spieler fuer den die KI zieht
    ''' </summary>
    ''' <remarks></remarks>
    Public Spieler As ObjektSpieler
    ''' <summary>
    ''' Der Modus in dem sich die Einheit die Gezogen wird befindet
    ''' </summary>
    ''' <remarks></remarks>
    Public KIModusEinheitenBefehl As KIModiExtern = KIModiExtern.Keiner
    ''' <summary>
    ''' Der Mouds in dem sich die KI im Moment befindet
    ''' </summary>
    ''' <remarks></remarks>
    Public KIModusIntern As KIModiIntern = KIModiIntern.StartWarten
    ''' <summary>
    ''' Nach welchem System Gebaeude besetzt werden
    ''' </summary>
    ''' <remarks></remarks>
    Protected Besetzngsprioritaet As Besetzungsprioritaeten
    Private Gluecksfaktore As Single = 0.0
    ''' <summary>
    ''' Anhand dieses Faktors berechnet die KI den durchschnittlichen Glueckswert beim Angriff
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property Gluecksfaktor() As Single
        Get
            Return Gluecksfaktore
        End Get
        Set(ByVal value As Single)
            If value > 1 Then
                value = 1
            ElseIf value < -1 Then
                value = -1
            End If
            Gluecksfaktore = value
        End Set
    End Property
    ''' <summary>
    ''' Wie oft wir bereits gebaut haben.
    ''' </summary>
    ''' <remarks></remarks>
    Protected AnzahldesBauens As Integer = 0
    ''' <summary>
    ''' Der Geldschaden den die Einheit bei einem Angriff mindestens verursachen muss gehoert zu den Startwerten
    ''' </summary>
    ''' <remarks></remarks>
    Protected MinimalerGeldschaden As Single = 0
    ''' <summary>
    ''' Die Einheit die die KI zieht
    ''' </summary>
    ''' <remarks></remarks>
    Protected AktuelleEinheit As ObjektEinheit = Nothing
    ''' <summary>
    ''' Das Ziel der momentanen Einheit.
    ''' </summary>
    ''' <remarks></remarks>
    Public AktuelleZiel As Point
    ''' <summary>
    ''' Das momentane Ziel einer Einheit
    ''' </summary>
    ''' <remarks></remarks>
    Protected Opfer As ObjektEinheit = Nothing
    ''' <summary>
    ''' Das Gebaeude auf dem die Einheit gebaut wird.
    ''' </summary>
    ''' <remarks></remarks>
    Protected BauGebaeude As ObjektGebaeude
    ''' <summary>
    ''' Dies sagt der KI wie lange sie warten soll
    ''' </summary>
    ''' <remarks></remarks>
    Public MaxKIWarteFrame = 12
    ''' <summary>
    ''' Sagt der KI das sie warten soll
    ''' </summary>
    ''' <remarks></remarks>
    Public KIZieht As Boolean = False
    Public KIWarteFrames As Integer
    Public Property KIWarteFrame() As Integer
        Get
            Return KIWarteFrames
        End Get
        Set(ByVal value As Integer)
            KIWarteFrames += 1
            If KIWarteFrames >= MaxKIWarteFrame Then
                KIWarteFrames = 0
                KIZieht = False
            End If
        End Set
    End Property
    ''' <summary>
    ''' Gibt an wie viel mehr Wert eigene Einheiten im Vergleich zu feindlichen sind.
    ''' </summary>
    ''' <remarks></remarks>
    Protected EigenerEinheitenWert As Single = 1
    ''' <summary>
    ''' Gibt an welche Felder beschossen werden und von wem (nicht wie viele)
    ''' 0=Fernkampf Feind Boden
    ''' 1=Nahkampf Feind Boden
    ''' 2=Geschuetzfeind
    ''' 3=eigene Fernkampf
    ''' 4=eigene Nahkampf
    ''' 5=Heilung Eigene
    ''' 6=Fernkampf Feind Luft
    ''' 7=Nahkampf Feind Luft
    ''' </summary>
    ''' <remarks></remarks>
    Protected Beschussfelder(,) As Byte = {}
    Public Function IsZielFernkampfBoden(ByVal X As Integer, ByVal Y As Integer) As Boolean
        Return GetBoolean(Beschussfelder(X, Y))(0)
    End Function
    Public Function IsZielFernkampfLuft(ByVal X As Integer, ByVal Y As Integer) As Boolean
        Return GetBoolean(Beschussfelder(X, Y))(6)
    End Function
    Public Function IsZielNahkampfBoden(ByVal X As Integer, ByVal Y As Integer) As Boolean
        Return GetBoolean(Beschussfelder(X, Y))(1)
    End Function
    Public Function IsZielNahkampfLuft(ByVal X As Integer, ByVal Y As Integer) As Boolean
        Return GetBoolean(Beschussfelder(X, Y))(7)
    End Function
    Public Function IsZielGeschuetz(ByVal X As Integer, ByVal Y As Integer) As Boolean
        Return GetBoolean(Beschussfelder(X, Y))(2)
    End Function
    Public Function IsDeckungFernkampf(ByVal X As Integer, ByVal Y As Integer) As Boolean
        Return GetBoolean(Beschussfelder(X, Y))(3)
    End Function
    Public Function IsDeckungNahkampf(ByVal X As Integer, ByVal Y As Integer) As Boolean
        Return GetBoolean(Beschussfelder(X, Y))(4)
    End Function
    Public Function IsDeckungHeilung(ByVal X As Integer, ByVal Y As Integer) As Boolean
        Return GetBoolean(Beschussfelder(X, Y))(5)
    End Function
    Public Function IsFernZielFuerEinheit(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer) As Boolean
        If Einheit.IsFlyingUnit Then
            Return IsZielFernkampfLuft(X, Y)
        Else
            Return IsZielFernkampfBoden(X, Y)
        End If
    End Function

    ''' <summary>
    ''' Die Einheit bei der wir gerade im Einheitenarray sind.
    ''' </summary>
    ''' <remarks></remarks>
    Protected MomentaneEinheit As Integer = 0
    ''' <summary>
    ''' wenn True beendet die KI ihren Zug in dem sie die KO's wechselt.
    ''' </summary>
    ''' <remarks></remarks>
    Protected RundenEndeMitWechsel As Boolean = False
    Structure Point2
        Public Sub New(ByVal P1 As Point, ByVal P2 As Point)
            Me.p1 = P1
            Me.p2 = P2
        End Sub
        Private p1 As Point
        Public Property Point1() As Point
            Get
                Return p1
            End Get
            Set(ByVal value As Point)
                p1 = value
            End Set
        End Property
        Private p2 As Point
        Public Property Point2() As Point
            Get
                Return p2
            End Get
            Set(ByVal value As Point)
                p2 = value
            End Set
        End Property
    End Structure
    ''' <summary>
    ''' Der Schaden den wir nehmen nur fuer NetzwerkKI
    ''' </summary>
    ''' <remarks></remarks>
    Protected AngreiferSchaden As Single
    ''' <summary>
    ''' Der Schaden den der Gegner nimmt nur fuer NetzwerkKI
    ''' </summary>
    ''' <remarks></remarks>
    Protected VerteidigerSchaden As Single
    ''' <summary>
    ''' So viel Schaden mehr muessen wir machen bei einem Nahkampf fuer ein lohnenden Angriff
    ''' </summary>
    ''' <remarks></remarks>
    Protected MinimaleTPDifferenz As Single = 0
    ''' <summary>
    ''' Der Prozentuale Anteil, den eine Einheit an Treibstoff haben darf damit sie sich nicht zurueck zieht.
    ''' </summary>
    ''' <remarks></remarks>
    Public MinimalerTreibstoff As Single = 0
    ''' <summary>
    ''' Das minmale Leben einer Einheit  damit sie sich nicht zurueck zieht.
    ''' </summary>
    ''' <remarks></remarks>
    Protected MinimaleKP As Integer = 0
    ''' <summary>
    ''' Der Prozentuale Anteil, den eine Einheit an Munition haben darf damit sie sich nicht zurueck zieht.
    ''' </summary>
    ''' <remarks></remarks>
    Public MinimaleMunition As Single = 0

    Public Shared Schlachtfeld As Integer = 0
#End Region
#Region "Start"
    ''' <summary>
    ''' Startet die KI und setzt ihre Startwerte fest
    ''' </summary>
    ''' <param name="neuSpieler"></param>
    ''' <remarks></remarks>
    Public Sub New(ByVal neuSpieler As ObjektSpieler, ByVal MinimalerGeldschaden As Single, ByVal EigenerEinheitenWert As Single, ByVal Gluecksfaktor As Single, ByVal Besetzungsprioriaet As Besetzungsprioritaeten, ByVal LohnendeOpfer As GeldTPAngriffsModus, ByVal MinimaleTPDifferenz As Single, ByVal MinimalerTreibstoff As Single, ByVal MinimaleKP As Integer, ByVal MinimaleMunition As Single)
        ObjektMaus.Visible = False
        Spieler = neuSpieler
        Me.MinimalerGeldschaden = MinimalerGeldschaden
        Me.EigenerEinheitenWert = EigenerEinheitenWert
        Me.Gluecksfaktor = Gluecksfaktor
        Me.Besetzngsprioritaet = Besetzungsprioriaet
        Me.MinimaleTPDifferenz = MinimaleTPDifferenz
        Me.MinimaleMunition = MinimaleMunition
        Me.MinimaleKP = MinimaleKP
        Me.MinimalerTreibstoff = MinimalerTreibstoff
        OpferBerechnung = LohnendeOpfer
    End Sub
    ''' <summary>
    ''' Launches the AI and initalizes some lower Stuff.
    ''' </summary>
    ''' <remarks></remarks>
    Public Overridable Sub LaunchAI()
        Schleife = False
        ObjektMaus.Visible = False
        ReDim Sichtfeld(Objektverwalter.Spielfeld.Breite - 1, Objektverwalter.Spielfeld.Hoehe - 1, ObjektSpielfeld.Luftschlacht)
        ReDim Beschussfelder(Objektverwalter.Spielfeld.Breite - 1, Objektverwalter.Spielfeld.Hoehe - 1)
        KIModusIntern = KIModiIntern.KIStart
        'Dies sind Standart initialisierungen die jede KI braucht
        Schlachtfeld = 0
        GetAllBuildings()
        CreateSicht(Sichtfeld, Spieler, False, True)
        GetBeschussfelder()
        StartNeuerKIThreat()
    End Sub
    Public Overridable Sub DisposeAI()
        ReDim Einheiten(-1)
        ReDim Sichtfeld(-1, -1, -1)
        ReDim Gebaeude(-1)
        ReDim Beschussfelder(-1, -1)
    End Sub

    ''' <summary>
    ''' Ok! Wir haben Einheiten mit einer Fabrik gebaut und wollen die natuerlich auch ziehen.
    ''' Sie muessen also geladen werden.
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub NeueEinheitenerstellt(ByVal Sortieren As EinheitenSortierKriterien)
        GetAllUnits(Sortieren)
        CreateSicht(Sichtfeld, Spieler)
    End Sub
    ''' <summary>
    ''' Fuegt alle nicht gezogenen Einheiten dem Einheitenarray hinzu
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub GetAllUnits(ByVal Sortieren As EinheitenSortierKriterien)
        Array.Resize(Einheiten, 0)
        Dim E As New Stack(Of ObjektEinheit)
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                If Not Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Hidden Then
                    If IsNothing(Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)) = False Then
                        If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld).Spieler = Spieler.Spieler Then
                            If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld).HatsichBewegt = False Then
                                E.Push(Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld))
                            End If
                        End If
                    End If
                End If
            Next
        Next
        Einheiten = E.ToArray
        Einheiten = SortUnits(Einheiten, Sortieren)
    End Sub
    Protected Function SortUnits(ByVal Units As ObjektEinheit(), ByVal Sortieren As EinheitenSortierKriterien) As ObjektEinheit()
        Select Case Sortieren
            Case EinheitenSortierKriterien.Zufall
                Dim Units2(Units.Length - 1) As ObjektEinheit
                For I = 0 To Units2.Length - 1
                    Dim I2 As Integer = Zufallszahl(0, Units.Length - I - 1)
                    Units2(I) = Units(I2)
                    Units(I2) = Units(Units.Length - I - 1)
                Next
                Return Units2
            Case EinheitenSortierKriterien.GroessterBewegungsradius
                Dim Units2(Units.Length - 1) As ObjektEinheit
                For I = 0 To Units2.Length - 1
                    Dim MaxMovementRange As Integer = -1
                    Dim E As Integer = -1
                    For I2 = 0 To Units.Length - I - 1
                        Dim MoveRange As Integer = Units(I2).GetMovementRange
                        If MoveRange > MaxMovementRange Then
                            E = I2
                            MaxMovementRange = MoveRange
                        ElseIf MoveRange = MaxMovementRange And Zufallszahl(0, 1) = 0 Then
                            E = I2
                            MaxMovementRange = MoveRange
                        End If
                    Next
                    Units2(I) = Units(E)
                    Units(E) = Units(Units.Length - I - 1)
                Next
                Return Units2
            Case EinheitenSortierKriterien.Preis
                Dim Units2(Units.Length - 1) As ObjektEinheit
                For I = 0 To Units2.Length - 1
                    Dim Preis As Integer = -1
                    Dim E As Integer = -1
                    For I2 = 0 To Units.Length - I - 1
                        Dim MoveRange As Integer = Units(I2).Kosten
                        If MoveRange > Preis Then
                            E = I2
                            Preis = MoveRange
                        ElseIf MoveRange = Preis And Zufallszahl(0, 1) = 0 Then
                            E = I2
                            Preis = MoveRange
                        End If
                    Next
                    Units2(I) = Units(E)
                    Units(E) = Units(Units.Length - I - 1)
                Next
                Return Units2
            Case EinheitenSortierKriterien.KleinsterBewegungsradius
                Dim Units2(Units.Length - 1) As ObjektEinheit
                For I = 0 To Units2.Length - 1
                    Dim MaxMovementRange As Integer = -1
                    Dim E As Integer = -1
                    For I2 = 0 To Units.Length - I - 1
                        Dim MoveRange As Integer = Units(I2).GetMovementRange
                        If MoveRange < MaxMovementRange Or MaxMovementRange < 0 Then
                            E = I2
                            MaxMovementRange = MoveRange
                        ElseIf MoveRange = MaxMovementRange And Zufallszahl(0, 1) = 0 Then
                            E = I2
                            MaxMovementRange = MoveRange
                        End If
                    Next
                    Units2(I) = Units(E)
                    Units(E) = Units(Units.Length - I - 1)
                Next
                Return Units2
            Case Else
                Return Units
        End Select
    End Function
    ''' <summary>
    ''' Fuegt alle Gebaeude der KI dir ihr momentan gehoeren dem Array hinzu.
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub GetAllBuildings()
        Array.Resize(Gebaeude, 0)
        Dim G As New Stack(Of ObjektGebaeude)
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                If Not Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Hidden Then
                    If IsNothing(Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebaeude) = False Then
                        If Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebaeude.Spieler = Spieler.Spieler Then
                            If Not Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebaeude.GetRealGebaeudeID = "VERWEIS" Then
                                Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebaeude.CanMoveAfterBuilding = New List(Of ObjektGebaeude.Variable)
                                G.Push(Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebaeude)
                            End If
                        Else
                            Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebaeude.CanMoveAfterBuilding = Nothing
                        End If
                    End If
                End If
            Next
        Next
        Gebaeude = G.ToArray
    End Sub
    Public Function SortGebaeude(ByVal G() As ObjektGebaeude, ByVal Sortieren As GebaeudeSortierKriterien) As ObjektGebaeude()
        Select Case Sortieren
            Case GebaeudeSortierKriterien.Zufall
                Dim G2 As New Stack(Of ObjektGebaeude)
                For I = 0 To G.Length - 1
                    Dim I2 As Integer = Zufallszahl(0, G.Length - I - 1)
                    G2.Push(G(I2))
                    G(I2) = G(G.Length - I - 1)
                Next
                Return G2.ToArray
            Case GebaeudeSortierKriterien.NaehestenZumFeind
                If ExistsEnemys(Spieler.Team) Then
                    Dim Entfernungen(G.Length - 1) As Integer
                    For I = 0 To G.Length - 1
                        Dim E As ObjektEinheit = Nothing
                        If TypeOf G(I) Is GebaeudeBasis Then
                            E = New EinheitFlak(Spieler.Spieler, G(I).Rechteck.X, G(I).Rechteck.Y, False)
                        ElseIf TypeOf G(I) Is GebaeudeFlughafen Then
                            E = New EinheitTarnkappenbomber(Spieler.Spieler, G(I).Rechteck.X, G(I).Rechteck.Y, False)
                        ElseIf TypeOf G(I) Is GebaeudeHafen Then
                            E = New EinheitKreuzer(Spieler.Spieler, G(I).Rechteck.X, G(I).Rechteck.Y, False)
                        ElseIf TypeOf G(I) Is GebaeudeLabor Then
                            E = New EinheitMech(Spieler.Spieler, G(I).Rechteck.X, G(I).Rechteck.Y, False)
                        ElseIf TypeOf G(I) Is GebaeudeStadt And G(I).GetBaulisteThisPlayer.Length > 0 Then
                            E = New EinheitFlak(Spieler.Spieler, G(I).Rechteck.X, G(I).Rechteck.Y, False)
                        End If
                        If E Is Nothing Then
                            Entfernungen(I) = -1
                        Else
                            Dim WSS As New Wegsuchsystem(E, E.X, E.Y, Objektverwalter.Spielfeld.MomentaneSchlacht, -1, False, Wegsuchsystem.SuchartenEinheiten.AlleEinheitenIgnorieren)
                            Entfernungen(I) = WSS.Wegsuchen(True, False)
                        End If
                    Next
                    Dim G2(G.Length - 1) As ObjektGebaeude
                    Dim MaxMovementRange As Integer = Objektverwalter.Spielfeld.Breite * Objektverwalter.Spielfeld.Hoehe
                    For I = 0 To G2.Length - 1

                        Dim GebaeudeStelle As Integer = 0
                        For I2 = 0 To G.Length - I - 1
                            If Entfernungen(I2) < MaxMovementRange And Entfernungen(I2) >= 0 Then
                                GebaeudeStelle = I2
                                MaxMovementRange = Entfernungen(I2)
                            ElseIf Entfernungen(I2) = MaxMovementRange And Entfernungen(I2) >= 0 And Zufallszahl(0, 1) = 0 Then
                                GebaeudeStelle = I2
                                MaxMovementRange = Entfernungen(I2)
                            End If
                        Next
                        G2(I) = G(GebaeudeStelle)
                        Entfernungen(GebaeudeStelle) = Entfernungen(Entfernungen.Length - I - 1)
                        G(GebaeudeStelle) = G(G.Length - I - 1)
                    Next
                    Return G2
                Else
                    Return SortGebaeude(G, GebaeudeSortierKriterien.Zufall)
                End If
            Case Else
                Return G
        End Select
    End Function
    Public Shared Function ExistsEnemys(ByVal Team As Char) As Boolean
        For Each Unit In Objektverwalter.Spielfeld.Einheiten
            If Unit IsNot Nothing Then
                If Not Objektverwalter.Spielfeld.Landschaften(Unit.X, Unit.Y, Unit.GetMap).Hidden Then
                    If Unit.GetSpieler.Team <> Team Then
                        Return True
                    End If
                End If
            End If
        Next
        Return False
    End Function

    ''' <summary>
    ''' Gibt die Anzahl der Infanteristen die dieser Spieler kontrolliert zurueck
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function CountInfanteristen() As Integer
        Dim Infanteristen As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                    If Not E Is Nothing Then
                        If E.Spieler = Spieler.Spieler Then
                            If E.KannBesetzen = True Then
                                If E.Leben > 0 Then
                                    Infanteristen += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return Infanteristen
    End Function
    ''' <summary>
    ''' Gibt die Anzahl der Einheiten von einem bestimmten Typ zurueck.
    ''' </summary>
    ''' <param name="EinheitenID"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function CountAnyUnit(ByVal EinheitenID As String) As Integer
        Dim Units As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                    If Not E Is Nothing Then
                        If E.Spieler = Spieler.Spieler Then
                            If E.Leben > 0 Then
                                If EinheitenID = E.EinheitenID Then
                                    Units += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return Units
    End Function
    ''' <summary>
    ''' Gibt alle Gebaeude einer Art zurueck
    ''' </summary>
    ''' <param name="GebaeudeID"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetBuildings(ByVal GebaeudeID As String) As ObjektGebaeude()
        Dim IDGebaeude As New Stack(Of ObjektGebaeude)
        For Each Besetzung In Gebaeude
            If Besetzung.GebaeudeID = GebaeudeID Then
                IDGebaeude.Push(Besetzung)
            End If
        Next
        Return IDGebaeude.ToArray
    End Function
    ''' <summary>
    ''' Zaehlt die Anzahl der Einheiten die noch Leben
    ''' </summary>
    ''' <remarks></remarks>
    Protected Function CountUnits() As Integer
        Dim Units As Integer = 0
        For I = 0 To Einheiten.Length - 1
            If IsNothing(Einheiten(I)) = False Then
                If Einheiten(I).Leben > 0 Then
                    Units += 1
                End If
            End If
        Next
        Return Units
    End Function
    ''' <summary>
    ''' Gibt alle Einheiten die gebaut werden koennen
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetAllBuildUnits(ByVal Bauliste() As String, ByVal X As Integer, ByVal Y As Integer) As Integer()
        Dim EinheitenIDs As New Stack(Of Integer)
        For I = 0 To Bauliste.Length - 1
            If ObjektLadeklasse.GetEinheitenkosten(Bauliste(I)) * Spieler.Teurungsrate(Bauliste(I), X, Y) <= Spieler.Fonds Then
                If Spieler.GetBauliste Is Nothing Then
                    EinheitenIDs.Push(I)
                ElseIf Spieler.GetBauliste.GetWert(Bauliste(I)) >= 0 Then
                    EinheitenIDs.Push(I)
                End If
            End If
        Next
        Return EinheitenIDs.ToArray
    End Function
    ''' <summary>
    ''' Fuehrt je nach KI Art und Zugfortschritt eine andere Untertine auf und fuehrt sie aus
    ''' </summary>
    ''' <remarks></remarks>
    Public MustOverride Sub KISchleife()
    Private FailedRestartingThread As Boolean = False
    Public Schleife As Boolean = False
    ''' <summary>
    ''' Fuehrt den Frame der KI aus
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub KIFrame()
        'Wir duerfen nur arbeiten wenn der Bild Backbuffer leer ist und alle Animationen abgespielt wurden.
        If BackbufferSpiel.GetBufferLength = 0 Then
            If Objektverwalter.Spielfeld.Animationen.Length = 0 Then
                If Schleife = False Then
                    If KIZieht = True Then
                        KIWarteFrame = 1
                        If KIZieht = False Then
                            WackUPThread()
                        End If
                    ElseIf FailedRestartingThread = True Then
                        WackUPThread()
                    End If
                ElseIf RundenEndeMitWechsel = False Then
                    'Die KI ist fertig dann beendet sie ihren Zug
                    KIThreat.Abort()
                    KIThreat = Nothing

                    If Objektverwalter.Spielfeld.AktuellerSpieler.KIStufe <> ObjektSpieler.KIStufen.Passiv Then
                        Dim Befehl As New KINetzwerkBefehl
                        Befehl.Befehl = ObjektKI.KIModiExtern.RundenEnde
                        Befehl.KooX = -1
                        Befehl.KooY = -1
                        Befehl.WegX = New Integer() {-1}
                        Befehl.WegY = New Integer() {-1}
                        Befehl.OpferX = -1
                        Befehl.OpferY = -1
                        Befehl.AngreiferSchaden = -1
                        Befehl.Verteidigerschaden = -1
                        Befehl.Spieler = Objektverwalter.Spielfeld.AktuellerSpieler.Spieler
                        Hauptmenue.NetzBefehlSenden(Befehl)
                    End If

                    Objektverwalter.Spielfeld.RundenEnde()
                Else
                    If ObjektKODialog.AktuellerDialog Is Nothing And ObjektKODialog.KOTextVorrat.Length = 0 Then
                        Objektverwalter.Spielfeld.RundenEnde()
                    End If
                End If
            End If
        End If
    End Sub
    ''' <summary>
    ''' Laesst den KIThread wieder arbeiten, wenn er bereit dazu ist.
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub WackUPThread()

        FailedRestartingThread = True
        'Die KI zieht nur wenn keine KO's sprechen
        Dim M As ObjektSpielMenue = Objektverwalter.Menue
        If KIThreat.ThreadState = Threading.ThreadState.WaitSleepJoin Then
            If Objektverwalter.Spielfeld.Animationen.Length = 0 Then
                If BackbufferSpiel.GetBufferLength = 0 Then
                    If Not M.Spielmodus = ObjektSpielMenue.Spielmodi.KOSprechen Then
                        If KIModusEinheitenBefehl = KIModiExtern.Keiner Then
                            If Objektverwalter.Spielfeld.AktuelleEinheit Is Nothing And Objektverwalter.Spielfeld.Angriff Is Nothing And Objektverwalter.Spielfeld.Laufen Is Nothing Then
                                'Wir haben keine Einheit ausgewaehlt und machen auch sonst keine Aktion.
                                KIThreat.Interrupt()
                            ElseIf Not Objektverwalter.Spielfeld.AktuelleEinheit Is Nothing And Objektverwalter.Spielfeld.Angriff Is Nothing And Objektverwalter.Spielfeld.Laufen Is Nothing Then
                                KIThreat.Interrupt()
                            ElseIf (Not Objektverwalter.Spielfeld.AktuelleEinheit Is Nothing) And Objektverwalter.Spielfeld.Angriff Is Nothing Then
                                Select Case KIModusIntern
                                    Case KIModiIntern.Transproterziehen
                                        KIThreat.Interrupt()
                                End Select
                            End If
                        Else
                            If Objektverwalter.Spielfeld.AktuelleEinheit Is Nothing And Objektverwalter.Spielfeld.Angriff Is Nothing Then
                                'Wir haben keine Einheit ausgewaehlt und machen auch sonst keine Aktion.
                                KIThreat.Interrupt()
                            ElseIf Objektverwalter.Spielfeld.Angriff Is Nothing And Objektverwalter.Spielfeld.Laufen Is Nothing Then
                                'Wir haben keine Einheit ausgewaehlt und machen auch sonst keine Aktion.
                                KIThreat.Interrupt()
                            ElseIf Objektverwalter.Spielfeld.Angriff Is Nothing And Not Objektverwalter.Spielfeld.Laufen Is Nothing Then
                                If Objektverwalter.Spielfeld.Laufen.Zielerreicht = True Then
                                    'Wir haben keine Einheit ausgewaehlt und machen auch sonst keine Aktion.
                                    KIThreat.Interrupt()
                                End If
                            End If
                        End If
                    End If
                End If
            End If
        End If
    End Sub
    ''' <summary>
    ''' Startet einen neuen KIThreat
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub StartNeuerKIThreat()
        If IsNothing(KIThreat) Then
            KIThreat = New Threading.Thread(AddressOf KISchleife)
            'wir lassen so das Spiel fluessiger erscheinen
            KIThreat.Priority = Threading.ThreadPriority.Lowest
            KIThreat.Name = "KI Threat"
            KIThreat.Priority = Threading.ThreadPriority.Highest
            KIThreat.Start()
        Else
            If KIThreat.ThreadState = Threading.ThreadState.Stopped Then
                If IsNothing(KIThreat) = False Then
                    KIThreat.Abort()
                End If
                KIThreat = Nothing
                KIThreat = New Threading.Thread(AddressOf KISchleife)
                KIThreat.Name = "KI Threat"
                KIThreat.Priority = Threading.ThreadPriority.Highest
                KIThreat.Start()
            End If
        End If

    End Sub
    ''' <summary>
    ''' Macht ein komplett Update fuer das Spielfeld, welche Felder angegriffen werden koennen oder Beschiessbar sind
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub GetBeschussfelder()
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                Dim Einheit As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If Not Einheit Is Nothing Then
                    'Auf dem Feld ist eine Einheit.
                    If Objektverwalter.Spielfeld.Spieler(Einheit.Spieler).Team <> Spieler.Team Then
                        Dim Nahkampffelder As Point2() = GetAllNahKampffelder(Einheit, False)
                        If Einheit.CanAttackGroundUnits Then
                            For Each Feld In Nahkampffelder
                                SetBoolean(1, True, Beschussfelder(Feld.Point2.X, Feld.Point2.Y))
                            Next
                        End If
                        If Einheit.CanAttackAirUnits Then
                            For Each Feld In Nahkampffelder
                                SetBoolean(6, True, Beschussfelder(Feld.Point2.X, Feld.Point2.Y))
                            Next
                        End If
                        Dim FernkampfFelder As Point() = GetAllFernKampfFelder(Einheit, Einheit.X, Einheit.Y, False)
                        If Einheit.CanAttackGroundUnits Then
                            For Each Feld In FernkampfFelder

                                SetBoolean(0, True, Beschussfelder(Feld.X, Feld.Y))
                            Next
                        End If
                        If Einheit.CanAttackAirUnits Then
                            For Each Feld In FernkampfFelder
                                SetBoolean(7, True, Beschussfelder(Feld.X, Feld.Y))
                            Next
                        End If
                    ElseIf Einheit.Spieler = Spieler.Spieler Then
                        Dim Nahkampffelder As Point2() = GetAllNahKampffelder(Einheit, False)
                        For Each Feld In Nahkampffelder
                            SetBoolean(4, True, Beschussfelder(Feld.Point2.X, Feld.Point2.Y))
                        Next
                        Dim FernkampfFelder As Point() = GetAllFernKampfFelder(Einheit, Einheit.X, Einheit.Y, False)
                        For Each Feld In FernkampfFelder
                            SetBoolean(3, True, Beschussfelder(Feld.X, Feld.Y))
                        Next
                    End If
                End If
                Dim Gebaeude As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebaeude
                If Not Gebaeude Is Nothing Then
                    'Auf dem Feld ist eine Einheit.
                    If Gebaeude.Spieler = Spieler.Spieler Then
                        If Gebaeude.Schaden < 0 Then
                            Dim Felder As Point() = Gebaeude.GetAngriffsFelder
                            For Each Feld In Felder
                                SetBoolean(5, True, Beschussfelder(Feld.X, Feld.Y))
                            Next
                        End If
                    ElseIf Not Objektverwalter.Spielfeld.Spieler(Gebaeude.Spieler).Team = Spieler.Team Then
                        If Gebaeude.Schaden > 0 Then
                            Dim Felder As Point() = Gebaeude.GetAngriffsFelder
                            For Each Feld In Felder
                                SetBoolean(2, True, Beschussfelder(Feld.X, Feld.Y))
                            Next
                        End If
                    End If
                End If
            Next
        Next
    End Sub
    ''' <summary>
    ''' Stellt ein Byte als Boolean dar.
    ''' </summary>
    ''' <param name="B"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetBoolean(ByVal B As Byte) As Boolean()
        Dim Bo() As Boolean = {False, False, False, False, False, False, False, False}
        If B - 128 >= 0 Then
            Bo(0) = True
            B -= 128
        End If
        If B - 64 >= 0 Then
            Bo(1) = True
            B -= 64
        End If
        If B - 32 >= 0 Then
            Bo(2) = True
            B -= 32
        End If
        If B - 16 >= 0 Then
            Bo(3) = True
            B -= 16
        End If
        If B - 8 >= 0 Then
            Bo(4) = True
            B -= 8
        End If
        If B - 4 >= 0 Then
            Bo(5) = True
            B -= 4
        End If
        If B - 2 >= 0 Then
            Bo(6) = True
            B -= 2
        End If
        If B - 1 >= 0 Then
            Bo(7) = True
            B -= 1
        End If
        Return Bo
    End Function
    ''' <summary>
    ''' Veraendert ein Bit eines bytes auf den Wert 1 bzw. 0
    ''' </summary>
    ''' <param name="Ort"></param>
    ''' <param name="Wert"></param>
    ''' <param name="B"></param>
    ''' <remarks></remarks>
    Protected Sub SetBoolean(ByVal Ort As Integer, ByVal Wert As Boolean, ByRef B As Byte)
        Dim Bo() As Boolean = GetBoolean(B)
        Select Case Ort
            Case 0
                If Bo(0) = True And Wert = False Then
                    B -= 128
                ElseIf Bo(0) = False And Wert = True Then
                    B += 128
                End If
            Case 1
                If Bo(1) = True And Wert = False Then
                    B -= 64
                ElseIf Bo(1) = False And Wert = True Then
                    B += 64
                End If
            Case 2
                If Bo(2) = True And Wert = False Then
                    B -= 32
                ElseIf Bo(2) = False And Wert = True Then
                    B += 32
                End If
            Case 3
                If Bo(3) = True And Wert = False Then
                    B -= 16
                ElseIf Bo(3) = False And Wert = True Then
                    B += 16
                End If
            Case 4
                If Bo(4) = True And Wert = False Then
                    B -= 8
                ElseIf Bo(4) = False And Wert = True Then
                    B += 8
                End If
            Case 5
                If Bo(5) = True And Wert = False Then
                    B -= 4
                ElseIf Bo(5) = False And Wert = True Then
                    B += 4
                End If
            Case 6
                If Bo(6) = True And Wert = False Then
                    B -= 2
                ElseIf Bo(6) = False And Wert = True Then
                    B += 2
                End If
            Case 7
                If Bo(7) = True And Wert = False Then
                    B -= 1
                ElseIf Bo(7) = False And Wert = True Then
                    B += 1
                End If
        End Select
    End Sub
    ''' <summary>
    ''' Laesst den KIThread einschlafen
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub KIPause()
        Dim P As Boolean = True
        While KIKonsolenPause Or P
            P = False
            Try
                Threading.Thread.Sleep(System.Threading.Timeout.Infinite)
            Catch
                If Not KIKonsolenPause Then
                    FailedRestartingThread = False
                    KIZieht = False
                    Exit While
                End If
            End Try
        End While
    End Sub
    ''' <summary>
    ''' Sorgt dafuer das wir warten und dann denn Einheiten Befehl ausfuehren.
    ''' </summary>
    ''' <param name="Befehl"></param>
    ''' <param name="Zeit"></param>
    ''' <remarks></remarks>
    Public Sub AufBefehlEndeWarten(ByVal Befehl As KIModiExtern, ByVal Zeit As Integer, ByVal Wait As Boolean)
        KIModusEinheitenBefehl = Befehl
        If Wait Then
            KIWarten(Zeit)
        Else
            If Objektverwalter.Spielfeld.Laufen IsNot Nothing Then
                If Not Objektverwalter.Spielfeld.Laufen.Zielerreicht Then
                    Objektverwalter.Spielfeld.Laufen.Laufen()
                    Objektverwalter.Spielfeld.Laufen.Zielerreicht = True
                End If
            End If

        End If
        DoBefehl(Wait)
    End Sub
    ''' <summary>
    ''' Veranlasst die KI nichts zu tun und zu warten
    ''' </summary>
    ''' <param name="Frames"></param>
    ''' <remarks></remarks>
    Protected Sub KIWarten(ByVal Frames As Integer)
        Dim M As ObjektSpielMenue = Objektverwalter.Menue
        If Not M.Spielmodus = ObjektSpielMenue.Spielmodi.KOSprechen Then
            M.Spielmodus = ObjektSpielMenue.Spielmodi.Nichts
        End If
        If Hauptmenue.Aufzeichnungsspulen Then
            MaxKIWarteFrame = 0
        Else
            MaxKIWarteFrame = Frames
        End If
        KIZieht = True
        KIPause()

    End Sub

    Protected Sub CreateVirtuellesLeben()
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If Not E Is Nothing Then
                    E.VirtuellesLeben = E.Leben
                    E.VirtuellerMeistSchaden = 0
                End If
            Next
        Next

    End Sub
#End Region
#Region "Allgemeines"
    ''' <summary>
    ''' Die KI erschafft eine KO EInheit
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub KOEinheitErschaffen()
        If Objektverwalter.Spielfeld.Regeln.KOSystem > KOSysteme.Gabe_Modus Then
            If Spieler.KOS(0).GetKOUnit Is Nothing Then
                Dim E2 As ObjektEinheit = Nothing
                Dim Ziel As New Point(-1, -1)
                Dim WSS2 As Wegsuchsystem = Nothing
                Dim Bew As Integer = 0
                For Each Einheit In Einheiten
                    If ExistUnit(Einheit) Then
                        If Einheit.IsUsingUnit(MinimalerTreibstoff, MinimaleMunition, MinimaleKP) Then
                            If Einheit.Kosten >= 6000 Then
                                If Einheit.Kosten / 2 <= Objektverwalter.Spielfeld.AktuellerSpieler.Fonds Then
                                    Dim WSS As Wegsuchsystem = CreateWSS(Einheit)
                                    For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                                        For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                                            If Not E2 Is Nothing Then
                                                If Einheit.Kosten >= E2.Kosten Then
                                                    If WSS.getBewegungspunktekosten(X, Y) >= 0 Then
                                                        If IsFeldLeer(X, Y, Einheit) Then
                                                            Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebaeude
                                                            If Not G Is Nothing Then
                                                                If G.GetSpieler.Team = Spieler.Team Then
                                                                    If E2.X = Einheit.X And E2.Y = Einheit.Y Then
                                                                        Dim B As Integer = WSS.getBewegungspunktekosten(X, Y)
                                                                        If G.Angriff = ObjektGebaeude.Angriffe.HQ And B < Bew Then
                                                                            E2 = Einheit
                                                                            Ziel = New Point(X, Y)
                                                                            WSS2 = WSS
                                                                            Bew = B
                                                                        ElseIf G.GetBauliste().Contains(Einheit.EinheitenID) Then
                                                                            If B < Bew Then
                                                                                E2 = Einheit
                                                                                Ziel = New Point(X, Y)
                                                                                WSS2 = WSS
                                                                                Bew = B
                                                                            End If
                                                                        End If
                                                                    ElseIf G.GetBauliste.Contains(Einheit.EinheitenID) Or G.Angriff = ObjektGebaeude.Angriffe.HQ Then
                                                                        If E2.Kosten < Einheit.Kosten Then
                                                                            E2 = Einheit
                                                                            Ziel = New Point(X, Y)
                                                                            WSS2 = WSS
                                                                            Bew = WSS.getBewegungspunktekosten(X, Y)
                                                                        End If
                                                                    End If
                                                                End If
                                                            End If
                                                        End If
                                                    End If
                                                End If
                                            Else
                                                If WSS.getBewegungspunktekosten(X, Y) >= 0 Then
                                                    If IsFeldLeer(X, Y, Einheit) Then
                                                        Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebaeude
                                                        If Not G Is Nothing Then
                                                            If G.GetSpieler.Team = Spieler.Team Then
                                                                If G.GetBauliste.Contains(Einheit.EinheitenID) Or G.Angriff = ObjektGebaeude.Angriffe.HQ Then
                                                                    E2 = Einheit
                                                                    Ziel = New Point(X, Y)
                                                                    WSS2 = WSS
                                                                    Bew = WSS.getBewegungspunktekosten(X, Y)
                                                                End If
                                                            End If
                                                        End If
                                                    End If
                                                End If
                                            End If
                                        Next
                                    Next
                                End If
                            End If
                        End If
                    End If
                Next
                If Not E2 Is Nothing Then
                    If WSS2.getBewegungspunktekosten(Ziel.X, Ziel.Y, E2.GetMap) <= E2.Bewegungspunkte Then
                        Einheitauswaehlen(E2, Ziel, KIModiExtern.CreateKOEinheit, Nothing, WSS2, 4)
                    Else
                        Einheitauswaehlen(E2, Ziel, KIModiExtern.Warten, Nothing, WSS2, 4)
                    End If
                End If
            End If
        End If
        MomentaneEinheit = 0
    End Sub
    ''' <summary>
    ''' Sorgt dafuer, dass die KI weiter zieht und zwar in dem sie die Schleife auf Null setzt...
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub EinheitGezogenVonVorneStarten()
        If KIModusIntern = KIModiIntern.Transproterziehen Then
            Select Case Spieler.KIStufe
                Case ObjektSpieler.KIStufen.Kinderleicht
                    GetAllUnits(EinheitenSortierKriterien.Zufall)
                Case ObjektSpieler.KIStufen.Einfach, ObjektSpieler.KIStufen.Normal
                    GetAllUnits(EinheitenSortierKriterien.GroessterBewegungsradius)
                Case ObjektSpieler.KIStufen.Mittel
                    GetAllUnits(EinheitenSortierKriterien.KleinsterBewegungsradius)
                Case Else
                    GetAllUnits(EinheitenSortierKriterien.Zufall)
            End Select
        End If
        KIModusIntern = KIModiIntern.GebaeudeAngriff
        MomentaneEinheit = 0
    End Sub
    ''' <summary>
    ''' Gibt das momentane Ziel einer Einheit zurueck.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetEinheitenZiel() As Point
        Return AktuelleZiel
    End Function

    ''' <summary>
    ''' Erstellt ein Wegsuchsystem fuer eine Runde.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function CreateWSS(ByVal Einheit As ObjektEinheit) As Wegsuchsystem
        Dim WSS As Wegsuchsystem = Nothing
        Dim Bewegunspunkte As Integer = Einheit.GetMovementRange

        If Bewegunspunkte <= Einheit.Treibstoff Then
            WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
        ElseIf Einheit.Treibstoff = -1 Then
            WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
        Else
            WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Einheit.Treibstoff)
        End If
        Return WSS
    End Function
    ''' <summary>
    ''' erstellt ein Wegsuchsystem fuer n-Felder
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="Reichweite"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function CreateWSS(ByVal Einheit As ObjektEinheit, ByVal Reichweite As Integer) As Wegsuchsystem
        Return New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Reichweite)
    End Function
    ''' <summary>
    ''' Gibt eines der Gebaeude das besetzt werden kann und Einheiten produzieren kann zurueck.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetBauGebaeudeZumBesetzen(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Point
        Dim Felder As Point() = GetAllBesetzungsfelder(Einheit, WSS, False)
        Dim MomFeld As New Point(-1, -1)
        Dim LetzteGebaeude As ObjektGebaeude = Nothing
        Dim Wegkosten As Integer = -1
        For Each Feld In Felder
            Dim Gebaeude As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(Feld.X, Feld.Y, Schlachtfeld).Gebaeude
            If Not Gebaeude Is Nothing Then
                If Gebaeude.GetBaulisteThisPlayer.Length > 0 Then
                    If MomFeld.X >= 0 Then
                        Select Case Besetzngsprioritaet
                            Case Besetzungsprioritaeten.Keine
                                If Zufallszahl(0, 1) = 1 Then
                                    MomFeld = Feld
                                    LetzteGebaeude = Gebaeude
                                End If
                            Case Besetzungsprioritaeten.FlughafebBasisHafenLaborHQStadt
                                If LetzteGebaeude.GebaeudeID = "FLUGHAFEN" Then
                                    If Gebaeude.GebaeudeID = "FLUGHAFEN" And Zufallszahl(0, 1) Then
                                        MomFeld = Feld
                                        LetzteGebaeude = Gebaeude
                                    End If
                                ElseIf Gebaeude.GebaeudeID = "FLUGHAFEN" Then
                                    MomFeld = Feld
                                    LetzteGebaeude = Gebaeude
                                ElseIf LetzteGebaeude.GebaeudeID = "BASIS" Then
                                    If Gebaeude.GebaeudeID = "BASIS" And Zufallszahl(0, 1) Then
                                        MomFeld = Feld
                                        LetzteGebaeude = Gebaeude
                                    End If
                                ElseIf Gebaeude.GebaeudeID = "BASIS" And Zufallszahl(0, 1) Then
                                    MomFeld = Feld
                                    LetzteGebaeude = Gebaeude
                                ElseIf LetzteGebaeude.GebaeudeID = "WERFT" Then
                                    If Gebaeude.GebaeudeID = "WERFT" And Zufallszahl(0, 1) Then
                                        MomFeld = Feld
                                        LetzteGebaeude = Gebaeude
                                    End If
                                ElseIf Gebaeude.GebaeudeID = "WERFT" And Zufallszahl(0, 1) Then
                                    MomFeld = Feld
                                    LetzteGebaeude = Gebaeude
                                ElseIf LetzteGebaeude.GebaeudeID = "LABOR" Then
                                    If Gebaeude.GebaeudeID = "LABOR" And Zufallszahl(0, 1) Then
                                        MomFeld = Feld
                                        LetzteGebaeude = Gebaeude
                                    End If
                                ElseIf Gebaeude.GebaeudeID = "LABOR" And Zufallszahl(0, 1) Then
                                    MomFeld = Feld
                                    LetzteGebaeude = Gebaeude
                                ElseIf LetzteGebaeude.GebaeudeID = "HQ" Then
                                    If Gebaeude.GebaeudeID = "HQ" And Zufallszahl(0, 1) Then
                                        MomFeld = Feld
                                        LetzteGebaeude = Gebaeude
                                    End If
                                ElseIf Gebaeude.GebaeudeID = "HQ" And Zufallszahl(0, 1) Then
                                    MomFeld = Feld
                                    LetzteGebaeude = Gebaeude
                                ElseIf LetzteGebaeude.GebaeudeID = "STADT" Then
                                    If Gebaeude.GebaeudeID = "STADT" And Zufallszahl(0, 1) Then
                                        MomFeld = Feld
                                        LetzteGebaeude = Gebaeude
                                    End If
                                ElseIf Gebaeude.GebaeudeID = "STADT" And Zufallszahl(0, 1) Then
                                    MomFeld = Feld
                                    LetzteGebaeude = Gebaeude
                                ElseIf Zufallszahl(0, 1) = 1 Then
                                    MomFeld = Feld
                                    LetzteGebaeude = Gebaeude
                                End If
                            Case Besetzungsprioritaeten.MeisteEinheiten
                                If LetzteGebaeude.GetBaulisteThisPlayer.Length < Gebaeude.GetBaulisteThisPlayer.Length Then
                                    MomFeld = Feld
                                    LetzteGebaeude = Gebaeude
                                ElseIf LetzteGebaeude.GetBaulisteThisPlayer.Length = Gebaeude.GetBaulisteThisPlayer.Length And Zufallszahl(0, 1) = 1 Then
                                    MomFeld = Feld
                                    LetzteGebaeude = Gebaeude
                                End If
                        End Select
                    Else
                        MomFeld = Feld
                        LetzteGebaeude = Gebaeude
                    End If
                End If
            End If
        Next
        If MomFeld.X < 0 And Felder.Length > 0 Then
            MomFeld = Felder(Zufallszahl(0, Felder.Length - 1))
        End If
        Return MomFeld
    End Function
    ''' <summary>
    ''' Gibt eines der Gebaeude zurueck die die Besetzungskriterien am meisten Erfuellen von der Einheit entfernt sind, aber in dieser Runde besetzt werden kann.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetWeitestesBesetzungsFeld(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Point
        Dim Felder As Point() = GetAllBesetzungsfelder(Einheit, WSS, False)
        Dim MomFeld As New Point(-1, -1)
        Dim Wegkosten As Integer = -1
        For Each Feld In Felder
            Dim WKosten As Integer = WSS.getBewegungspunktekosten(Feld.X, Feld.Y)
            If WKosten > Wegkosten Then
                Wegkosten = WKosten
                MomFeld = Feld
            ElseIf WKosten = Wegkosten And Zufallszahl(0, 1) = 1 Then
                Wegkosten = WKosten
                MomFeld = Feld
            End If
        Next
        Return MomFeld
    End Function
    ''' <summary>
    ''' Gibt alle Felder zurueck die in dieser Runde besetzt werden koennen und frei sind.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <param name="MitEinheitdrauf">Wenn True werden alle Gebaeude zurueck gegeben die besetzt werden koennen auch wenn eine Einheit draufsteht</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetAllBesetzungsfelder(ByVal Einheit As ObjektEinheit, Optional ByRef WSS As Wegsuchsystem = Nothing, Optional ByVal MitEinheitdrauf As Boolean = False) As Point()
        Dim Felder As New Stack(Of Point)
        If Einheit.KannBesetzen = True Then
            'Wir initialiesieren evtl. das Wegsuchsystem.
            Dim Bewegunspunkte As Integer = Einheit.GetMovementRange
            If WSS Is Nothing Then
                If Bewegunspunkte <= Einheit.Treibstoff Then
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
                ElseIf Einheit.Treibstoff = -1 Then
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
                Else
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Einheit.Treibstoff)
                End If
            End If
            For Y1 = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                For X1 = 0 To Objektverwalter.Spielfeld.Breite - 1
                    Dim Kosten As Integer = WSS.getBewegungspunktekosten(X1, Y1)
                    Dim neuerPunkt As Point = New Point(X1, Y1)
                    If Kosten >= 0 And Kosten <= Bewegunspunkte Then
                        If Objektverwalter.Spielfeld.OnMap(neuerPunkt.X, neuerPunkt.Y) Then
                            Dim Gebaeud As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X1, Y1, Schlachtfeld).Gebaeude
                            If Not Gebaeud Is Nothing Then
                                If Objektverwalter.Spielfeld.Spieler(Gebaeud.Spieler).Team <> Spieler.Team Then
                                    If Gebaeud.Besetzung > 0 Or Gebaeud.Angriff = ObjektGebaeude.Angriffe.Silo Then
                                        If Felder.Contains(neuerPunkt) = False Then
                                            If MitEinheitdrauf = True Then
                                                Felder.Push(neuerPunkt)
                                            ElseIf Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld) Is Nothing Then
                                                Felder.Push(neuerPunkt)
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        End If
        Return Felder.ToArray
    End Function
    ''' <summary>
    ''' Gibt zurueck wie gross der Geldschaden waere wenn wir von diesem Feld aus angreifen wuerden.
    ''' </summary>
    ''' <param name="Angreifer"></param>
    ''' <param name="ATKX"></param>
    ''' <param name="ATKY"></param>
    ''' <param name="Verteidiger"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetGeldschaden(ByVal Angreifer As ObjektEinheit, ByVal ATKX As Integer, ByVal ATKY As Integer, ByVal Verteidiger As ObjektEinheit, ByRef TPDifferenz As Single) As Single
        Dim Glueck As Point = Spieler.GetGlueckPech(ATKX, ATKY)
        AktuelleZiel = New Point(ATKX, ATKY)
        If Gluecksfaktor > 0 Then
            Glueck.X *= Gluecksfaktor
        Else
            Glueck.X = Glueck.Y * Gluecksfaktor
        End If
        Dim OpferLeben As Single = Verteidiger.Leben
        Dim Schaden As Single = Objektverwalter.Schadensberechnung(Angreifer, ATKX, ATKY, Verteidiger.X, Verteidiger.Y, Angreifer.Leben, OpferLeben, False, True, Glueck.X, Verteidiger, False)(0)
        Glueck = Objektverwalter.Spielfeld.Spieler(Verteidiger.Spieler).GetGlueckPech(Verteidiger.X, Verteidiger.Y)
        If Gluecksfaktor > 0 Then
            Glueck.X *= Gluecksfaktor
        Else
            Glueck.X = Glueck.Y * Gluecksfaktor
        End If

        OpferLeben = Angreifer.Leben
        Dim EigenSchaden As Single = Objektverwalter.Schadensberechnung(Verteidiger, Verteidiger.X, Verteidiger.Y, ATKX, ATKY, Verteidiger.Leben - Schaden, OpferLeben, True, True, Glueck.X, Angreifer, False)(0)
        Dim Verteidigerleben As Single = Verteidiger.Leben - Schaden
        If Schaden > Verteidiger.Leben Then
            Schaden = Verteidiger.Leben
            Verteidigerleben = 0
        End If
        TPDifferenz = Schaden - EigenSchaden
        Dim GegenSchaden As Single = EigenSchaden * Angreifer.Kosten * Spieler.Teurungsrate(Angreifer, ATKX, ATKY) * EigenerEinheitenWert
        Schaden = Verteidiger.Kosten * Schaden * Objektverwalter.Spielfeld.Spieler(Verteidiger.Spieler).Teurungsrate(Verteidiger, Verteidiger.X, Verteidiger.Y)

        If GegenSchaden <= 0 Or Verteidigerleben <= 0 Then
            Schaden /= 10000
            If Schaden < MinimalerGeldschaden Then
                Schaden = MinimalerGeldschaden
            End If
        Else
            Schaden = Schaden / GegenSchaden
        End If
        If Verteidiger.MaximaleReichweite > 1 Then
            Schaden += Verteidiger.Kosten / 1000
        End If
        Return Schaden
    End Function
    ''' <summary>
    ''' Gibt das beste Opfer dieser Einheit von der momentanen Position zurueck.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns>Gibt (-1,-1) zurueck wenn kein Opfer gefunden</returns>
    ''' <remarks></remarks>
    Protected Function GetBestesNahkampfOpfer(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Point2
        Return GetBestesNahkampfOpfer(Einheit, WSS, GetAllNahKampffelder(Einheit, True, WSS))
    End Function
    ''' <summary>
    ''' Gibt das beste Opfer dieser Einheit von der momentanen Position zurueck.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns>Gibt (-1,-1) zurueck wenn kein Opfer gefunden</returns>
    ''' <remarks></remarks>
    Protected Function GetBestesNahkampfOpfer(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem, ByVal Opfer() As Point2) As Point2
        If Opfer.Length > 0 Then
            Dim MomentanesOpfer As Integer = -1
            Dim MomentanerSchaden As Single = 0
            Dim MomentaneTPDifferenz As Single = -100
            For I = 0 To Opfer.Length - 1
                Dim UnserOpfer As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Opfer(I).Point2.X, Opfer(I).Point2.Y, Schlachtfeld)
                'Wir berechnen wie viel Geldschaden wir anrichten wuerden
                Dim TPDifferenz As Single = 0
                Dim Schaden As Single = GetGeldschaden(Einheit, Opfer(I).Point1.X, Opfer(I).Point1.Y, UnserOpfer, TPDifferenz)
                Select Case OpferBerechnung
                    Case GeldTPAngriffsModus.NurTP
                        If TPDifferenz > MinimaleTPDifferenz Then
                            If TPDifferenz > MomentaneTPDifferenz Then
                                MomentaneTPDifferenz = TPDifferenz
                                MomentanesOpfer = I
                            ElseIf TPDifferenz = MomentaneTPDifferenz And Zufallszahl(0, 1) = 1 Then
                                MomentaneTPDifferenz = TPDifferenz
                                MomentanesOpfer = I
                            End If
                        End If
                    Case GeldTPAngriffsModus.Beides
                        If TPDifferenz > MinimaleTPDifferenz Then
                            If Schaden >= MinimalerGeldschaden Then
                                If TPDifferenz > MomentaneTPDifferenz And Schaden > MomentanerSchaden Then
                                    MomentaneTPDifferenz = TPDifferenz
                                    MomentanerSchaden = Schaden
                                    MomentanesOpfer = I
                                ElseIf TPDifferenz = MomentaneTPDifferenz And Schaden >= MomentanerSchaden And Zufallszahl(0, 1) = 1 Then
                                    MomentaneTPDifferenz = TPDifferenz
                                    MomentanerSchaden = Schaden
                                    MomentanesOpfer = I
                                ElseIf TPDifferenz >= MomentaneTPDifferenz And Schaden = MomentanerSchaden And Zufallszahl(0, 1) = 1 Then
                                    MomentaneTPDifferenz = TPDifferenz
                                    MomentanerSchaden = Schaden
                                    MomentanesOpfer = I
                                End If
                            End If
                        End If
                    Case GeldTPAngriffsModus.NurGeld
                        If Schaden >= MinimalerGeldschaden Then
                            If Schaden > MomentanerSchaden Then
                                MomentanerSchaden = Schaden
                                MomentanesOpfer = I
                            ElseIf Schaden = MomentanerSchaden And Zufallszahl(0, 1) = 1 Then
                                MomentanerSchaden = Schaden
                                MomentanesOpfer = I
                            End If
                        End If
                End Select
            Next
            If MomentanesOpfer < 0 Then
                Return New Point2(New Point(-1, -1), New Point(-1, -1))
            Else
                Return Opfer(MomentanesOpfer)
            End If
        Else
            Return New Point2(New Point(-1, -1), New Point(-1, -1))
        End If
    End Function
    ''' <summary>
    ''' Gibt das beste Opfer dieser Einheit von der momentanen Position zurueck.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns>Gibt (-1,-1) zurueck wenn kein Opfer gefunden</returns>
    ''' <remarks></remarks>
    Protected Function GetBestesFernkampfOpfer(ByVal Einheit As ObjektEinheit) As Point
        Return GetBestesFernkampfOpfer(Einheit, GetAllFernKampfFelder(Einheit, Einheit.X, Einheit.Y, True))
    End Function
    ''' <summary>
    ''' Gibt das beste Opfer dieser Einheit von der momentanen Position zurueck. Berechnet nach dem Geldschaden.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns>Gibt (-1,-1) zurueck wenn kein Opfer gefunden</returns>
    ''' <remarks></remarks>
    Protected Function GetBestesFernkampfOpfer(ByVal Einheit As ObjektEinheit, ByVal Opfer() As Point) As Point
        If Opfer.Length > 0 Then
            Dim MomentanesOpfer As Integer = 0
            Dim MomentanerSchaden As Integer = 0
            For I = 0 To Opfer.Length - 1
                Dim UnserOpfer As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Opfer(I).X, Opfer(I).Y, Schlachtfeld)
                If Not UnserOpfer Is Nothing Then
                    Dim Glueck As Point = Spieler.GetGlueckPech(Einheit.X, Einheit.Y)
                    If Gluecksfaktor > 0 Then
                        Glueck.X *= Gluecksfaktor
                    Else
                        Glueck.X = Glueck.Y * Gluecksfaktor
                    End If
                    Dim OpferLeben As Single = UnserOpfer.Leben
                    Dim Schaden As Integer = UnserOpfer.Kosten * Objektverwalter.Spielfeld.Spieler(UnserOpfer.Spieler).Teurungsrate(UnserOpfer, UnserOpfer.X, UnserOpfer.Y) * Objektverwalter.Schadensberechnung(Einheit, Einheit.X, Einheit.Y, UnserOpfer.X, UnserOpfer.Y, Einheit.Leben, OpferLeben, False, True, Glueck.X, UnserOpfer, False)(0)
                    If Schaden > MomentanerSchaden Then
                        MomentanerSchaden = Schaden
                        MomentanesOpfer = I
                    ElseIf Schaden = MomentanerSchaden And Zufallszahl(0, 1) = 1 Then
                        MomentanerSchaden = Schaden
                        MomentanesOpfer = I
                    End If
                Else
                    'Wir greifen ein Gebaeude oder eine Landschaft an.
                    If Objektverwalter.Spielfeld.Landschaften(Opfer(I).X, Opfer(I).Y, Schlachtfeld).Leben > 0 Then
                        If MomentanerSchaden = 0 Then
                            If MomentanesOpfer <> 0 Then
                                If Zufallszahl(0, 1) = 0 Then
                                    MomentanesOpfer = I
                                End If
                            Else
                                MomentanesOpfer = I
                            End If
                        End If
                    Else
                        Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(Opfer(I).X, Opfer(I).Y, Schlachtfeld).Gebaeude
                        Dim Schaden As Integer = ObjektLadeklasse.GetGebaeudeKosten(G.GebaeudeID, G.Spieler) / G.GetMaxLeben * Tabellenverwalter.GetWert(Einheit.Waffe2, "Gebaeude")
                        If Schaden > MomentanerSchaden Then
                            MomentanerSchaden = Schaden
                            MomentanesOpfer = I
                        ElseIf Schaden = MomentanerSchaden And Zufallszahl(0, 1) = 1 Then
                            MomentanerSchaden = Schaden
                            MomentanesOpfer = I
                        End If
                    End If
                End If
            Next
            Return Opfer(MomentanesOpfer)
        Else
            Return New Point(-1, -1)
        End If
    End Function
    ''' <summary>
    ''' Gibt das beste Opfer dieser Einheit von der momentanen Position zurueck. Berechnet nach dem Geldschaden aber primaeres Ziel sind Fernwaffen.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns>Gibt (-1,-1) zurueck wenn kein Opfer gefunden</returns>
    ''' <remarks></remarks>
    Protected Overridable Function GetBestesFernkampfOpferFirstFernwaffen(ByVal Einheit As ObjektEinheit, ByVal Opfer() As Point) As Point
        If Opfer.Length > 0 Then
            Dim MomentanesOpfer As Integer = -1
            Dim MomentanerSchaden As Integer = 0
            Dim Fernwaffe As Boolean = False 'Haben wir schon eine Fernwaffe gefunden?
            For I = 0 To Opfer.Length - 1
                Dim UnserOpfer As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Opfer(I).X, Opfer(I).Y, Schlachtfeld)
                If Not UnserOpfer Is Nothing Then
                    Dim Glueck As Point = Spieler.GetGlueckPech(Einheit.X, Einheit.Y)
                    If Gluecksfaktor > 0 Then
                        Glueck.X *= Gluecksfaktor
                    Else
                        Glueck.X = Glueck.Y * Gluecksfaktor
                    End If
                    Dim OpferLeben As Single = UnserOpfer.Leben
                    Dim Schaden As Integer = UnserOpfer.Kosten * Objektverwalter.Spielfeld.Spieler(UnserOpfer.Spieler).Teurungsrate(UnserOpfer, UnserOpfer.X, UnserOpfer.Y) * Objektverwalter.Schadensberechnung(Einheit, Einheit.X, Einheit.Y, UnserOpfer.X, UnserOpfer.Y, Einheit.Leben, OpferLeben, False, True, Glueck.X, UnserOpfer, False)(0)
                    If Fernwaffe = False Then
                        If UnserOpfer.MaximaleReichweite > 1 Then
                            MomentanerSchaden = Schaden
                            MomentanesOpfer = I
                            Fernwaffe = True
                        Else
                            If Schaden > MomentanerSchaden Then
                                MomentanerSchaden = Schaden
                                MomentanesOpfer = I
                            ElseIf Schaden = MomentanerSchaden And Zufallszahl(0, 1) = 1 Then
                                MomentanerSchaden = Schaden
                                MomentanesOpfer = I
                            End If
                        End If
                    ElseIf UnserOpfer.MaximaleReichweite > 1 Then
                        If Schaden > MomentanerSchaden Then
                            MomentanerSchaden = Schaden
                            MomentanesOpfer = I
                        ElseIf Schaden = MomentanerSchaden And Zufallszahl(0, 1) = 1 Then
                            MomentanerSchaden = Schaden
                            MomentanesOpfer = I
                        End If
                    End If
                Else
                    'Wir greifen ein Gebaeude oder eine Landschaft an.
                    If Objektverwalter.Spielfeld.Landschaften(Opfer(I).X, Opfer(I).Y, Schlachtfeld).Leben > 0 Then
                        If MomentanerSchaden = 0 Then
                            If MomentanesOpfer < 0 Then
                                MomentanesOpfer = I
                            ElseIf Zufallszahl(0, 1) = 0 Then
                                MomentanesOpfer = I
                            End If
                        End If
                    Else
                        Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(Opfer(I).X, Opfer(I).Y, Schlachtfeld).Gebaeude
                        Dim Schaden As Integer = ObjektLadeklasse.GetGebaeudeKosten(G.GebaeudeID, G.Spieler) / G.GetMaxLeben * Tabellenverwalter.GetWert(Einheit.Waffe2, "Gebaeude")
                        If Schaden > MomentanerSchaden Then
                            MomentanerSchaden = Schaden
                            MomentanesOpfer = I
                        ElseIf Schaden = MomentanerSchaden And Zufallszahl(0, 1) = 1 Then
                            MomentanerSchaden = Schaden
                            MomentanesOpfer = I
                        End If
                    End If
                End If
            Next
            If MomentanesOpfer >= 0 Then
                Return Opfer(MomentanesOpfer)
            Else
                Return New Point(-1, -1)
            End If
        Else
            Return New Point(-1, -1)
        End If
    End Function
    ''' <summary>
    ''' Gibt alle Felder zurueck die in diesem Zug per Nahkampf erreicht werden koennen
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="NurMitFeind"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetAllNahKampffelder(ByVal Einheit As ObjektEinheit, Optional ByVal NurMitFeind As Boolean = True, Optional ByRef WSS As Wegsuchsystem = Nothing) As Point2()
        Dim Felder As New Stack(Of Point2)
        If Not Einheit.Waffe1 = "Keine" Or (Einheit.MinimaleReichweite = 1 And Einheit.Munition > 0) Then
            'Wir haben eine Nahkampfeinheit
            Dim Bewegunspunkte As Integer = Einheit.GetMovementRange
            If WSS Is Nothing Then
                If Bewegunspunkte <= Einheit.Treibstoff Then
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
                ElseIf Einheit.Treibstoff = -1 Then
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
                Else
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Einheit.Treibstoff)
                End If
            End If
            For Y1 = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                For X1 = 0 To Objektverwalter.Spielfeld.Breite - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X1, Y1, Schlachtfeld).Hidden Then
                        Dim Kosten As Integer = WSS.getBewegungspunktekosten(X1, Y1)
                        Dim neuerPunkt As Point = New Point(X1, Y1)
                        If Kosten >= 0 And Kosten <= Bewegunspunkte Then
                            If Objektverwalter.Spielfeld.OnMap(neuerPunkt.X, neuerPunkt.Y) Then
                                If IsFeldLeer(neuerPunkt.X, neuerPunkt.Y, Einheit) = True Then
                                    If Sichtfeld(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld) = True Then
                                        If ExistFeld(Felder, New Point2(neuerPunkt, neuerPunkt)) = False Then
                                            If NurMitFeind = False Then
                                                Felder.Push(New Point2(neuerPunkt, neuerPunkt))
                                            Else
                                                GetNahAngriffsFelderVonFeld(Einheit, neuerPunkt, Felder)
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        ElseIf Objektverwalter.Spielfeld.OnMap(neuerPunkt.X, neuerPunkt.Y) Then
                            Dim X2 As Integer = X1
                            Dim Y2 As Integer = Y1
                            For I = 0 To 3
                                Select Case I
                                    Case 0
                                        X2 -= 1
                                    Case 1
                                        X2 += 1
                                        Y2 -= 1
                                    Case 2
                                        X2 += 1
                                        Y2 += 1
                                    Case 3
                                        X2 -= 1
                                        Y2 += 1
                                End Select
                                If Objektverwalter.Spielfeld.OnMap(X2, Y2) Then
                                    Kosten = WSS.getBewegungspunktekosten(X2, Y2)
                                    Dim P2 As New Point(X2, Y2)
                                    If Kosten >= 0 And Kosten <= Bewegunspunkte Then
                                        If Objektverwalter.Spielfeld.OnMap(P2.X, P2.Y) Then
                                            If IsFeldLeer(P2.X, P2.Y, Einheit) = True Then
                                                If Sichtfeld(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld) = True Then
                                                    If ExistFeld(Felder, New Point2(P2, neuerPunkt)) = False Then
                                                        If NurMitFeind = True Then
                                                            If Not Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld) Is Nothing Then
                                                                If Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Spieler).Team <> Spieler.Team Then
                                                                    If KannAngegriffenWerden(Einheit, Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld), False, P2) = True Then
                                                                        Felder.Push(New Point2(P2, neuerPunkt))
                                                                    End If
                                                                End If
                                                            End If
                                                        Else
                                                            Felder.Push(New Point2(P2, neuerPunkt))
                                                        End If
                                                    End If
                                                End If
                                            End If
                                        End If
                                    End If
                                End If
                            Next
                        End If
                    End If
                Next
            Next
        End If
        Return Felder.ToArray
    End Function
    ''' <summary>
    ''' Gibt alle Felder zurueck die in diesem Zug per Nahkampf erreicht werden koennen und nicht von Fernwaffen unseres Typs beschossen werden koennen
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="NurMitFeind"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetAllNahKampffelderWithNoIndirectFire(ByVal Einheit As ObjektEinheit, Optional ByVal NurMitFeind As Boolean = True, Optional ByRef WSS As Wegsuchsystem = Nothing) As Point2()
        Dim Felder As New Stack(Of Point2)
        If Not Einheit.Waffe1 = "Keine" Or Einheit.MinimaleReichweite = 1 Then
            'Wir haben eine Nahkampfeinheit
            Dim Bewegunspunkte As Integer = Einheit.GetMovementRange
            If WSS Is Nothing Then
                If Bewegunspunkte <= Einheit.Treibstoff Then
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
                ElseIf Einheit.Treibstoff = -1 Then
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
                Else
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Einheit.Treibstoff)
                End If
            End If
            For Y1 = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                For X1 = 0 To Objektverwalter.Spielfeld.Breite - 1
                    Dim Kosten As Integer = WSS.getBewegungspunktekosten(X1, Y1)
                    Dim neuerPunkt As Point = New Point(X1, Y1)
                    If Kosten >= 0 And Kosten <= Bewegunspunkte Then
                        If Objektverwalter.Spielfeld.OnMap(neuerPunkt.X, neuerPunkt.Y) Then

                            If IsFeldLeer(neuerPunkt.X, neuerPunkt.Y, Einheit) = True Then
                                If Sichtfeld(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld) = True Then
                                    If ExistFeld(Felder, New Point2(neuerPunkt, neuerPunkt)) = False Then
                                        If NurMitFeind = False Then
                                            Felder.Push(New Point2(neuerPunkt, neuerPunkt))
                                        Else
                                            GetNahAngriffsFelderVonFeld(Einheit, neuerPunkt, Felder)
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    ElseIf Objektverwalter.Spielfeld.OnMap(neuerPunkt.X, neuerPunkt.Y) Then
                        Dim X2 As Integer = X1
                        Dim Y2 As Integer = Y1
                        For I = 0 To 3
                            Select Case I
                                Case 0
                                    X2 -= 1
                                Case 1
                                    X2 += 1
                                    Y2 -= 1
                                Case 2
                                    X2 += 1
                                    Y2 += 1
                                Case 3
                                    X2 -= 1
                                    Y2 += 1
                            End Select
                            If Objektverwalter.Spielfeld.OnMap(X2, Y2) Then
                                Kosten = WSS.getBewegungspunktekosten(X2, Y2)
                                Dim P2 As New Point(X2, Y2)
                                If Kosten >= 0 And Kosten <= Bewegunspunkte Then
                                    If Objektverwalter.Spielfeld.OnMap(P2.X, P2.Y) Then
                                        If IsFeldLeer(P2.X, P2.Y, Einheit) = True Then
                                            If Sichtfeld(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld) = True Then
                                                If ExistFeld(Felder, New Point2(P2, neuerPunkt)) = False Then
                                                    If NurMitFeind = True Then
                                                        If Not Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld) Is Nothing Then
                                                            If Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Spieler).Team <> Spieler.Team Then
                                                                If KannAngegriffenWerden(Einheit, Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld), False, P2) = True Then
                                                                    Felder.Push(New Point2(P2, neuerPunkt))
                                                                End If
                                                            End If
                                                        End If
                                                    Else
                                                        Felder.Push(New Point2(P2, neuerPunkt))
                                                    End If
                                                End If
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        Next
                    End If
                Next
            Next
        End If
        Return Felder.ToArray
    End Function
    ''' <summary>
    ''' Gibt die Felder zurueck die von diesem Feld aus angegriffen werden koennen
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="neuerPunkt"></param>
    ''' <param name="Felder"></param>
    ''' <remarks></remarks>
    Protected Sub GetNahAngriffsFelderVonFeld(ByVal Einheit As ObjektEinheit, ByVal neuerPunkt As Point, ByRef Felder As Stack(Of Point2))
        Dim X2 As Integer = neuerPunkt.X
        Dim Y2 As Integer = neuerPunkt.Y
        For I = 0 To 3
            Select Case I
                Case 0
                    X2 -= 1
                Case 1
                    X2 += 1
                    Y2 -= 1
                Case 2
                    X2 += 1
                    Y2 += 1
                Case 3
                    X2 -= 1
                    Y2 += 1
            End Select
            If Objektverwalter.Spielfeld.OnMap(X2, Y2) Then
                Dim P2 As New Point(X2, Y2)
                If Sichtfeld(P2.X, P2.Y, Schlachtfeld) = True Then
                    If ExistFeld(Felder, New Point2(neuerPunkt, P2)) = False Then
                        If Not Objektverwalter.Spielfeld.Einheiten(P2.X, P2.Y, Schlachtfeld) Is Nothing Then
                            If Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Einheiten(P2.X, P2.Y, Schlachtfeld).Spieler).Team <> Spieler.Team Then
                                If KannAngegriffenWerden(Einheit, Objektverwalter.Spielfeld.Einheiten(P2.X, P2.Y, Schlachtfeld), False, neuerPunkt) = True Then
                                    Felder.Push(New Point2(neuerPunkt, P2))
                                End If
                            End If
                        End If
                    End If
                End If
            End If
        Next
    End Sub
    ''' <summary>
    ''' Gibt alle Fernkampffelder zurueck die von einem Punkt beschossen werden koennen
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <param name="NurMitFeind">Gibt nur die Felder zurueck auf denen ein Feind steht.</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetAllFernKampfFelder(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer, Optional ByVal NurMitFeind As Boolean = True) As Point()

        Dim Felder As New Stack(Of Point)
        If Einheit.MaximaleReichweite > 1 Then
            If Einheit.Munition > 0 Then
                Dim MaximaleReichweite As Integer = Einheit.MaximaleReichweite
                Dim MinimaleReichweite As Integer = Einheit.MinimaleReichweite
                Dim Kreis(,) As Integer = Kreisfunktion(MaximaleReichweite)
                If MaximaleReichweite > 1 Then
                    For X1 = 0 To MaximaleReichweite * 2
                        For Y1 = 0 To MaximaleReichweite * 2
                            If Kreis(X1, Y1) >= MinimaleReichweite Then
                                Dim neuerPunkt As Point = New Point(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1)
                                If Objektverwalter.Spielfeld.OnMap(neuerPunkt.X, neuerPunkt.Y) Then
                                    If Sichtfeld(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld) = True Then
                                        If Not Objektverwalter.Spielfeld.Landschaften(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Hidden Then
                                            If Felder.Contains(neuerPunkt) = False Then
                                                If NurMitFeind = True Then
                                                    If Not Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld) Is Nothing Then
                                                        If KannAngegriffenWerden(Einheit, Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld), True, New Point(X, Y)) = True Then
                                                            Felder.Push(neuerPunkt)
                                                        End If
                                                    End If
                                                Else
                                                    Felder.Push(neuerPunkt)
                                                End If
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        Next
                    Next
                End If
            End If
        End If
        Return Felder.ToArray
    End Function
    ''' <summary>
    ''' Gibt alle Fernkampffelder zurueck die Angegriffen werden koennen.
    ''' Wenn keine Einheiten gefunden werden suchen wir Gebaeude.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <param name="NurMitFeind"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetAllFernKampfFelderGebaeude(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer, Optional ByVal NurMitFeind As Boolean = True) As Point()
        Dim Felder As New Stack(Of Point)
        If Einheit.MaximaleReichweite > 1 Then
            Dim MaximaleReichweite As Integer = Einheit.MaximaleReichweite
            Dim MinimaleReichweite As Integer = Einheit.MinimaleReichweite
            Dim Kreis(,) As Integer = Kreisfunktion(MaximaleReichweite)
            For X1 = 0 To MaximaleReichweite * 2
                For Y1 = 0 To MaximaleReichweite * 2
                    If Kreis(X1, Y1) >= MinimaleReichweite Then
                        Dim neuerPunkt As Point = New Point(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1)
                        If Objektverwalter.Spielfeld.OnMap(neuerPunkt.X, neuerPunkt.Y) Then
                            If Sichtfeld(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld) = True Then
                                If Felder.Contains(neuerPunkt) = False Then
                                    If NurMitFeind = True Then
                                        If Not Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld) Is Nothing Then
                                            If KannAngegriffenWerden(Einheit, Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld), True, New Point(X, Y)) = True Then
                                                Felder.Push(neuerPunkt)
                                            End If
                                        End If
                                    Else
                                        Felder.Push(neuerPunkt)
                                    End If
                                End If
                            End If
                        End If
                    End If
                Next
            Next
            If Felder.Count = 0 Then
                'Jetzt suchen wir Gebaeude
                For X1 = 0 To MaximaleReichweite * 2
                    For Y1 = 0 To MaximaleReichweite * 2
                        If Kreis(X1, Y1) >= MinimaleReichweite Then
                            If Objektverwalter.Spielfeld.OnMap(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1) Then
                                If Spieler.NeutraleGebaeudeAngriff = True Then
                                    If Objektverwalter.Spielfeld.Landschaften(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1, Schlachtfeld).Leben > 0 Then
                                        Felder.Push(New Point(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1))
                                    Else
                                        Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1, Schlachtfeld).Gebaeude
                                        If Not G Is Nothing Then
                                            If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                                If G.GetKP(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1, False) > 0 Then
                                                    Felder.Push(New Point(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1))
                                                End If
                                            End If
                                        End If
                                    End If
                                Else
                                    Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X1, Y1, Schlachtfeld).Gebaeude
                                    If Not G Is Nothing Then
                                        If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                            If G.GetKP(X1, Y1, False) > 0 Then
                                                Felder.Push(New Point(X1, Y1))
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    Next
                Next
            End If
        End If
        Return Felder.ToArray
    End Function
    ''' <summary>
    ''' Gibt das beste Opfer zurueck wen wir uns vor dem Schiessen noch bewegen.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetBestesFernkampfFeldmitBewegung(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Point2
        Dim Opfer() As Point2 = GetAllFernkampfFeldermitBewegung(Einheit, WSS)
        If Opfer.Length > 0 Then
            Dim MomentanesOpfer As Integer = 0
            Dim MomentanerSchaden As Integer = 0
            For I = 0 To Opfer.Length - 1
                Dim UnserOpfer As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Opfer(I).Point2.X, Opfer(I).Point2.Y, Schlachtfeld)
                Dim Glueck As Point = Spieler.GetGlueckPech(Opfer(I).Point1.X, Opfer(I).Point1.Y)
                If Gluecksfaktor > 0 Then
                    Glueck.X += Gluecksfaktor
                Else
                    Glueck.X = Glueck.Y * Gluecksfaktor
                End If
                Dim OpferLeben As Single = UnserOpfer.Leben
                Dim Schaden As Integer = UnserOpfer.Kosten * Objektverwalter.Spielfeld.Spieler(UnserOpfer.Spieler).Teurungsrate(UnserOpfer, UnserOpfer.X, UnserOpfer.Y) * Objektverwalter.Schadensberechnung(Einheit, Opfer(I).Point1.X, Opfer(I).Point1.Y, UnserOpfer.X, UnserOpfer.Y, Einheit.Leben, OpferLeben, False, True, Glueck.X, UnserOpfer, False)(0)
                If Schaden > MomentanerSchaden Then
                    MomentanerSchaden = Schaden
                    MomentanesOpfer = I
                ElseIf Schaden = MomentanerSchaden And Zufallszahl(0, 1) = 1 Then
                    MomentanerSchaden = Schaden
                    MomentanesOpfer = I
                End If
            Next
            Return Opfer(MomentanesOpfer)
        Else
            Return New Point2(New Point(-1, -1), New Point(-1, -1))
        End If
    End Function
    ''' <summary>
    ''' Gibt alle Felder zurueck die durch ziehen und schiessen mit einer Fernwaffe beschossen werden koennen.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetAllFernkampfFeldermitBewegung(ByVal Einheit As ObjektEinheit, Optional ByRef WSS As Wegsuchsystem = Nothing) As Point2()
        Dim Felder As New Stack(Of Point2)
        If Einheit.MaximaleReichweite > 1 Then
            Dim Bewegunspunkte As Integer = Einheit.GetMovementRange
            If WSS Is Nothing Then
                If Bewegunspunkte <= Einheit.Treibstoff Then
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
                ElseIf Einheit.Treibstoff = -1 Then
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
                Else
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Einheit.Treibstoff)
                End If
            End If
            For Y1 = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                For X1 = 0 To Objektverwalter.Spielfeld.Breite - 1
                    Dim Kosten As Integer = WSS.getBewegungspunktekosten(X1, Y1)
                    Dim neuerPunkt As Point = New Point(X1, Y1)
                    If Kosten >= 0 And Kosten <= Bewegunspunkte Then
                        If Objektverwalter.Spielfeld.OnMap(neuerPunkt.X, neuerPunkt.Y) Then
                            If IsFeldLeer(neuerPunkt.X, neuerPunkt.Y, Einheit) = True Then
                                'So dieses Feld kann betreten werden und jetzt schiessen wir von ihm aus.
                                Dim Felder2 As Point() = GetAllFernKampfFelder(Einheit, neuerPunkt.X, neuerPunkt.Y, True)
                                For Each Feld In Felder2
                                    Felder.Push(New Point2(neuerPunkt, Feld))
                                Next
                            End If
                        End If
                    End If
                Next
            Next
        End If
        Return Felder.ToArray
    End Function
    ''' <summary>
    ''' Ueberprueft ob ein Feld bereits einem Array hinzugefuegt wurden ist
    ''' </summary>
    ''' <param name="Felder"></param>
    ''' <param name="Feld"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function ExistFeld(ByVal Felder As Point(), ByVal Feld As Point) As Boolean
        For Each F In Felder
            If F.X = Feld.X And F.Y = Feld.Y Then
                Return True
            End If
        Next
        Return False
    End Function
    ''' <summary>
    ''' Gibt zurueck ob ein Doppelpunkt m Array enthalten ist
    ''' </summary>
    ''' <param name="Felder"></param>
    ''' <param name="Feld"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function ExistFeld(ByVal Felder As Stack(Of Point2), ByVal Feld As Point2) As Boolean
        For Each NFeld In Felder
            If NFeld.Point1.X = Feld.Point1.X Then
                If NFeld.Point1.Y = Feld.Point1.Y Then
                    If NFeld.Point2.X = Feld.Point2.X Then
                        If NFeld.Point2.Y = Feld.Point2.Y Then
                            Return True
                        End If
                    End If
                End If
            End If
        Next
        Return False
    End Function

    ''' <summary>
    ''' Gibt zurueck ob die Einheit von unserer Angegriffen werden kann.
    ''' </summary>
    ''' <param name="Angreifer"></param>
    ''' <param name="Verteidiger"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function KannAngegriffenWerden(ByVal Angreifer As ObjektEinheit, ByVal Verteidiger As ObjektEinheit, ByVal Fernkampf As Boolean, ByVal Pos As Point) As Boolean
        If ExistUnit(Verteidiger) Then
            If Objektverwalter.Spielfeld.Spieler(Verteidiger.Spieler).Team <> Spieler.Team Then
                Dim Distanz As Integer
                If Pos.X >= 0 Then
                    Distanz = Verteidiger.GetDistance(Pos)
                Else
                    Distanz = Angreifer.GetDistance(Verteidiger)
                End If
                If Verteidiger.GetTarnung Then
                    If Verteidiger.Bewegungsart <> Angreifer.Bewegungsart Or Fernkampf Then
                        Return False
                    End If
                End If
                If Not Angreifer.Waffe1 = "Keine" Then
                    If Distanz = 1 Then
                        If Tabellenverwalter.GetWert(Angreifer.Waffe1, Verteidiger.EinheitenID) >= 0 Then
                            Return True
                        ElseIf Not Angreifer.Waffe2 = "Keine" And Angreifer.Munition > 0 Then
                            If Fernkampf Then
                                If Distanz > 1 And Distanz >= Angreifer.MinimaleReichweite And Distanz <= Angreifer.MaximaleReichweite Then
                                    If Tabellenverwalter.GetWert(Angreifer.Waffe2, Verteidiger.EinheitenID) >= 0 Then
                                        Return True
                                    End If
                                End If
                            ElseIf Not Fernkampf Then
                                If Distanz = 1 Then
                                    If Tabellenverwalter.GetWert(Angreifer.Waffe2, Verteidiger.EinheitenID) >= 0 Then
                                        Return True
                                    End If
                                End If
                            End If
                        End If
                    ElseIf Not Angreifer.Waffe2 = "Keine" And Angreifer.Munition > 0 Then
                        If Fernkampf Then
                            If Distanz > 1 And Distanz >= Angreifer.MinimaleReichweite And Distanz <= Angreifer.MaximaleReichweite Then
                                If Tabellenverwalter.GetWert(Angreifer.Waffe2, Verteidiger.EinheitenID) >= 0 Then
                                    Return True
                                End If
                            End If
                        ElseIf Not Fernkampf Then
                            If Distanz = 1 Then
                                If Tabellenverwalter.GetWert(Angreifer.Waffe2, Verteidiger.EinheitenID) >= 0 Then
                                    Return True
                                End If
                            End If
                        End If
                    End If
                ElseIf Not Angreifer.Waffe2 = "Keine" And Angreifer.Munition > 0 Then
                    If Fernkampf Then
                        If Distanz > 1 And Distanz >= Angreifer.MinimaleReichweite And Distanz <= Angreifer.MaximaleReichweite Then
                            If Tabellenverwalter.GetWert(Angreifer.Waffe2, Verteidiger.EinheitenID) >= 0 Then
                                Return True
                            End If
                        End If
                    ElseIf Not Fernkampf Then
                        If Distanz = 1 Then
                            If Tabellenverwalter.GetWert(Angreifer.Waffe2, Verteidiger.EinheitenID) >= 0 Then
                                Return True
                            End If
                        End If
                    End If
                End If
            End If
        End If
        Return False
    End Function
    ''' <summary>
    ''' Gibt zurueck ob die Einheit von unserer Angegriffen werden kann, beruecksichtigt nicht die Entfernung
    ''' </summary>
    ''' <param name="Angreifer"></param>
    ''' <param name="Verteidiger"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function KannAngegriffenWerden(ByVal Angreifer As ObjektEinheit, ByVal Verteidiger As ObjektEinheit) As Boolean
        If Not Verteidiger Is Nothing Then
            If Verteidiger.GetTarnung() Then
                If Verteidiger.Bewegungsart <> Angreifer.Bewegungsart Then
                    Return False
                End If
            End If
            If Objektverwalter.Spielfeld.Spieler(Verteidiger.Spieler).Team <> Spieler.Team Then
                If Not Angreifer.Waffe1 = "Keine" Then
                    If Tabellenverwalter.GetWert(Angreifer.Waffe1, Verteidiger.EinheitenID) >= 0 Then
                        Return True
                    ElseIf Not Angreifer.Waffe2 = "Keine" And Angreifer.Munition > 0 Then
                        If Tabellenverwalter.GetWert(Angreifer.Waffe2, Verteidiger.EinheitenID) >= 0 Then
                            Return True
                        Else
                            Return False
                        End If
                    End If
                ElseIf Not Angreifer.Waffe2 = "Keine" And Angreifer.Munition > 0 Then
                    If Tabellenverwalter.GetWert(Angreifer.Waffe2, Verteidiger.EinheitenID) >= 0 Then
                        Return True
                    Else
                        Return False
                    End If
                Else
                    Return False
                End If
            End If
        End If
        Return False
    End Function
    ''' <summary>
    ''' Gibt das Feld zurueck auf das wir ziehen sollten um moeglichst bald angreifen zu koennen. Mit einer Nahkampfeinheit
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetNaehestenNahkampfFeind(ByVal Einheit As ObjektEinheit, Optional ByRef WSS As Wegsuchsystem = Nothing) As Point
        Dim Ziel As New Point(-1, -1)
        Dim Ziel2 As New Point(-1, -1)
        Dim MomentaneWegkosten As Integer = -1
        Dim MomentaneWegkosten2 As Integer = -1
        If Einheit.MinimaleReichweite = 1 Then
            If WSS Is Nothing Then
                WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, -1)
            End If
            Dim BewMax As Integer = 0
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    Dim L As ObjektLandschaft = Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld)
                    Dim Bew As Integer = WSS.getRundeDiskret(WSS.getBewegungspunktekosten(X, Y), False)
                    If Bew > 0 Then
                        'Wir koennen das Feld erreichen
                        If KannNahkampfvonFeldgemachtwerden(Einheit, X, Y) = True Then
                            If Bew < MomentaneWegkosten And Bew > BewMax Then
                                MomentaneWegkosten = Bew
                                Ziel = New Point(X, Y)
                            ElseIf Bew = MomentaneWegkosten And Zufallszahl(0, 1) = 1 Then
                                MomentaneWegkosten = Bew
                                Ziel = New Point(X, Y)
                            ElseIf MomentaneWegkosten = -1 Then
                                MomentaneWegkosten = Bew
                                Ziel = New Point(X, Y)
                            End If
                        ElseIf Bew = 0 Then
                            If MomentaneWegkosten < 0 Then
                                MomentaneWegkosten = Bew
                                Ziel = New Point(X, Y)
                            End If
                        End If
                    End If
                Next
            Next
        End If
        If MomentaneWegkosten2 - MomentaneWegkosten > Einheit.GetMovementRange * 2 And Ziel2.X >= 0 Then
            Return Ziel2
        ElseIf MomentaneWegkosten < 0 And MomentaneWegkosten2 >= 0 Then
            Return Ziel2
        Else
            Return Ziel
        End If
    End Function
    ''' <summary>
    ''' Gibt das Feld zurueck auf das wir ziehen sollten um moeglichst bald angreifen zu koennen. Mit einer Nahkampfeinheit
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetNaehestenFeindVonGebaeude(ByVal Einheit As ObjektEinheit, Optional ByRef WSS As Wegsuchsystem = Nothing) As Point
        Dim Ziel As New Point(-1, -1)
        Dim MomentaneWegkosten As Integer = -1
        If Einheit.MinimaleReichweite = 1 Then
            If WSS Is Nothing Then
                WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, -1)
            End If
            Dim BewMax As Integer = Einheit.GetMovementRange
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    Dim Bew As Integer = WSS.getBewegungspunktekosten(X, Y)
                    If Bew >= 0 Then
                        If IsFeldLeer(X, Y, Einheit) Then
                            'Wir koennen das Feld erreichen
                            If KannNahkampfGemachtwerden(Einheit, X, Y) = True Then
                                If Bew < MomentaneWegkosten And Bew > BewMax Then
                                    MomentaneWegkosten = Bew
                                    Ziel = New Point(X, Y)
                                ElseIf Bew = MomentaneWegkosten And Zufallszahl(0, 1) = 1 Then
                                    MomentaneWegkosten = Bew
                                    Ziel = New Point(X, Y)
                                ElseIf MomentaneWegkosten = -1 Then
                                    MomentaneWegkosten = Bew
                                    Ziel = New Point(X, Y)
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        End If
        Return Ziel
    End Function
    ''' <summary>
    ''' Ueberprueft ob per Nahangriff eine Einheit
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function KannNahkampfvonFeldgemachtwerden(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer) As Boolean
        Dim X2 As Integer = X
        Dim Y2 As Integer = Y
        Dim P As New Point(X, Y)
        For I = 0 To 3
            Select Case I
                Case 0
                    X2 -= 1
                Case 1
                    X2 += 1
                    Y2 -= 1
                Case 2
                    X2 += 1
                    Y2 += 1
                Case 3
                    X2 -= 1
                    Y2 += 1
            End Select
            If Objektverwalter.Spielfeld.OnMap(X2, Y2) Then
                If Not Objektverwalter.Spielfeld.Landschaften(X2, Y2, Schlachtfeld).Hidden Then
                    If KannAngegriffenWerden(Einheit, Objektverwalter.Spielfeld.Einheiten(X2, Y2, Schlachtfeld), False, P) = True Then
                        Return True
                    End If
                End If
            End If
        Next
        Return False
    End Function
    ''' <summary>
    ''' Ueberprueft ob per Nahangriff eine Einheit
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function KannNahkampfGemachtwerden(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer) As Boolean
        Dim X2 As Integer = X
        Dim Y2 As Integer = Y
        Dim P As New Point(X, Y)
        For I = 0 To 3
            Select Case I
                Case 0
                    X2 -= 1
                Case 1
                    X2 += 1
                    Y2 -= 1
                Case 2
                    X2 += 1
                    Y2 += 1
                Case 3
                    X2 -= 1
                    Y2 += 1
            End Select
            If Objektverwalter.Spielfeld.OnMap(X2, Y2) Then
                If KannAngegriffenWerden(Einheit, Objektverwalter.Spielfeld.Einheiten(X2, Y2, Schlachtfeld)) = True Then
                    Return True
                End If
            End If
        Next
        Return False
    End Function
    ''' <summary>
    ''' Gibt das Feld zurueck auf das wir laufen sollten, weil wir weiter laufen wollen als wir koennen
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetZielFeldfuerdieseRunde(ByRef WSS As Wegsuchsystem, ByVal Ziel As Point, ByVal Einheit As ObjektEinheit) As Point
        Dim Bewegunspunkte As Integer = Einheit.GetMovementRange
        WSS.Ziel(Ziel.X, Ziel.Y, True)
        Return New Point(WSS.WegpunkteX(WSS.WegpunkteX.Length - 1), WSS.WegpunkteY(WSS.WegpunkteY.Length - 1))
    End Function
    ''' <summary>
    ''' Sucht die naeheste Besetzung und gibt das naeheste freie Feld zurueck auf das wir in diesem Zug ziehen muessen.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetNaehesteBesetzung(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Point
        Dim Ziel As New Point(-1, -1)
        Dim MomentaneWegkosten As Integer = -1
        If Einheit.MinimaleReichweite = 1 Then
            If WSS Is Nothing Then
                WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, -1)
            End If
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe
                    If WSS.getBewegungspunktekosten(X, Y) >= 0 Then
                        If IsFeldLeer(X, Y, Einheit) Then
                            'Wir koennen das Feld erreichen
                            If IsBesetzungDrauf(X, Y) = True Then
                                If WSS.getBewegungspunktekosten(X, Y) < MomentaneWegkosten Then
                                    MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                    Ziel = New Point(X, Y)
                                ElseIf WSS.getBewegungspunktekosten(X, Y) = MomentaneWegkosten And Zufallszahl(0, 1) = 1 Then
                                    MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                    Ziel = New Point(X, Y)
                                ElseIf MomentaneWegkosten = -1 Then
                                    MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                    Ziel = New Point(X, Y)
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        End If
        Return Ziel
    End Function
    ''' <summary>
    ''' Gibt zurueck ob auf diesem Feld ein Gebaeude ist, dass besetzt werden kann.
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function IsBesetzungDrauf(ByVal X As Integer, ByVal Y As Integer) As Boolean
        Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebaeude
        If G Is Nothing Then
            Return False
        Else
            If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                If G.IsBesetzung(Spieler.Spieler) = True Then
                    Return True
                End If
            Else
                Return False
            End If
        End If
        Return False
    End Function
    ''' <summary>
    ''' Gibt eines der naehesten Felder zurueck von dem aus ohne Bewegung in der naechsten Runde angegriffen werden koennte.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetNaehestesFernkampffeld(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Point
        Dim Ziel As New Point(-1, -1)
        Dim MomentaneWegkosten As Integer = -1
        If Einheit.MaximaleReichweite > 1 Then
            If WSS Is Nothing Then
                WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, -1)
            End If
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe
                    If WSS.getBewegungspunktekosten(X, Y) >= 0 Then
                        If IsFeldLeer(X, Y, Einheit) = True Then
                            'Wir koennen das Feld erreichen
                            If KannFernkampfGemachtWerden(Einheit, X, Y) = True Then
                                If WSS.getBewegungspunktekosten(X, Y) < MomentaneWegkosten Then
                                    MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                    Ziel = New Point(X, Y)
                                ElseIf WSS.getBewegungspunktekosten(X, Y) = MomentaneWegkosten And Zufallszahl(0, 1) = 1 Then
                                    MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                    Ziel = New Point(X, Y)
                                ElseIf MomentaneWegkosten = -1 Then
                                    MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                    Ziel = New Point(X, Y)
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        End If
        Return Ziel
    End Function
    ''' <summary>
    ''' Gibt an ob von diesem Feld aus ein Fernkampf ausgefuehrt werden kann.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function KannFernkampfGemachtWerden(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer) As Boolean
        Dim Felder As Point() = {}
        If Einheit.MaximaleReichweite > 1 Then
            Dim MaximaleReichweite As Integer = Einheit.MaximaleReichweite
            Dim MinimaleReichweite As Integer = Einheit.MinimaleReichweite
            Dim Kreis(,) As Integer = Kreisfunktion(MaximaleReichweite)
            If MaximaleReichweite > 1 Then
                For X1 = 0 To MaximaleReichweite * 2
                    For Y1 = 0 To MaximaleReichweite * 2
                        If Kreis(X1, Y1) >= MinimaleReichweite Then
                            Dim neuerPunkt As Point = New Point(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1)
                            If Objektverwalter.Spielfeld.OnMap(neuerPunkt.X, neuerPunkt.Y) Then
                                If Not Objektverwalter.Spielfeld.Landschaften(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Hidden Then
                                    If Not Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld) Is Nothing Then
                                        If Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).IsGetarnt(Spieler.Spieler) = False Then
                                            If KannAngegriffenWerden(Einheit, Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld), True, New Point(X, Y)) = True Then
                                                Return True
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    Next
                Next
            End If
        End If
        Return False
    End Function
    ''' <summary>
    ''' Gibt die Reichweite der Einheit zurueck.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetBewegungspunkte(ByVal Einheit As ObjektEinheit) As Integer
        Dim Bewegunspunkte As Integer = Einheit.GetMovementRange
        Return Bewegunspunkte
    End Function
    ''' <summary>
    ''' Gibt an ob das Feld leer ist
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function IsFeldLeer(ByVal X As Integer, ByVal Y As Integer, ByVal AktuelleEinheit As ObjektEinheit) As Boolean
        If Not Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Hidden Then
            If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld) Is Nothing Then
                Return True
            Else
                If X = AktuelleEinheit.X And Y = AktuelleEinheit.Y Then
                    Return True
                Else
                    Return False
                End If
            End If
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Gibt zurueck ob das Feld leer ist.
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function IsFeldLeer(ByVal X As Integer, ByVal Y As Integer) As Boolean
        If IsNothing(Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)) Then
            Return True
        ElseIf Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld).Leben <= 0 Then
            Return True
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Ueberprueft ob die Einheit noch lebt und ob sie Nicht nichts ist
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function ExistUnit(ByVal Einheit As ObjektEinheit) As Boolean
        If Not Einheit Is Nothing Then
            If Einheit.Leben > 0 Then
                If Einheit.X >= 0 And Einheit.Y >= 0 Then
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Einheit.X, Einheit.Y, Schlachtfeld)
                    If E Is Nothing Then
                        Return False
                    ElseIf E.Equals(Einheit) Then
                        Return True
                    End If
                Else
                    Return False
                End If
            Else
                Return False
            End If
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Gibt alle freien Felder zurueck die Leer sind und in dieser Runde betreten werden koennen.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetFreeFelder(ByVal Einheit As ObjektEinheit, Optional ByRef WSS As Wegsuchsystem = Nothing, Optional ByVal NoProduction As Boolean = False) As Point()
        Dim Felder As New Stack(Of Point)
        'Wir haben eine Nahkampfeinheit
        Dim Bewegunspunkte As Integer = Einheit.GetMovementRange
        If WSS Is Nothing Then
            If Bewegunspunkte <= Einheit.Treibstoff Then
                WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
            ElseIf Einheit.Treibstoff = -1 Then
                WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
            Else
                WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Einheit.Treibstoff)
            End If
        End If
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                If Not Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Hidden Then
                    If WSS.getBewegungspunktekosten(X, Y) >= 0 Then
                        If WSS.getBewegungspunktekosten(X, Y) <= Einheit.GetMovementRange Then
                            'Das Feld ist betretbar und frei?
                            If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld) Is Nothing Then
                                If NoProduction Then
                                    Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebaeude
                                    If G IsNot Nothing Then
                                        If G.GetSpieler.Team = Spieler.Team Then
                                            If G.GetBaulisteThisPlayer.Length = 0 Then
                                                Felder.Push(New Point(X, Y))
                                            End If
                                        Else
                                            Felder.Push(New Point(X, Y))
                                        End If
                                    Else
                                        Felder.Push(New Point(X, Y))
                                    End If
                                Else
                                    Felder.Push(New Point(X, Y))
                                End If
                            End If
                        End If
                    End If
                End If
            Next
        Next
        Return Felder.ToArray
    End Function
    ''' <summary>
    ''' Gibt das beste Ziel fuer einen Angriff zurueck.
    ''' Achtung: Bei Laser, Schocklaser, Monolith, Kristall wird immer das Gebaeude zurueck gegeben als Ziel.
    ''' -1,-1 Bedeutet kein Ziel
    ''' </summary>
    ''' <param name="Gebaeude"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetBestesGebaeudeFeuer(ByVal Gebaeude As ObjektGebaeude) As Point
        Dim Punkt As New Point(-1, -1)
        Select Case Gebaeude.Angriff
            Case ObjektGebaeude.Angriffe.SchussN
                Return GetBestesSchussZiel(Gebaeude)
            Case ObjektGebaeude.Angriffe.SchussO
                Return GetBestesSchussZiel(Gebaeude)
            Case ObjektGebaeude.Angriffe.SchussS
                Return GetBestesSchussZiel(Gebaeude)
            Case ObjektGebaeude.Angriffe.SchussW
                Return GetBestesSchussZiel(Gebaeude)
            Case ObjektGebaeude.Angriffe.DreiStrahlN
                Return New Point(Gebaeude.Rechteck.X, Gebaeude.Rechteck.Y)
            Case ObjektGebaeude.Angriffe.DreiStrahlO
                Return New Point(Gebaeude.Rechteck.X, Gebaeude.Rechteck.Y)
            Case ObjektGebaeude.Angriffe.DreiStrahlS
                Return New Point(Gebaeude.Rechteck.X, Gebaeude.Rechteck.Y)
            Case ObjektGebaeude.Angriffe.DreiStrahlW
                Return New Point(Gebaeude.Rechteck.X, Gebaeude.Rechteck.Y)
            Case ObjektGebaeude.Angriffe.Strahl
                Return New Point(Gebaeude.Rechteck.X, Gebaeude.Rechteck.Y)
            Case ObjektGebaeude.Angriffe.Kreis
                Return New Point(Gebaeude.Rechteck.X, Gebaeude.Rechteck.Y)
            Case Else
                Return Punkt
        End Select
    End Function
    ''' <summary>
    ''' Gibt das Zielfeld zurueck bei welchem wir den meisten Geldschaden verursachen.
    ''' </summary>
    ''' <param name="Gebaeude"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetBestesSchussZiel(ByVal Gebaeude As ObjektGebaeude) As Point
        Dim Ziele As Point() = Gebaeude.GeschuetzZiele
        'So auf diese Felder kann geschossen werden
        Dim BestesZiel As Integer = -1
        Dim Geldschaden As Integer = 0
        If Ziele.Length > 0 Then
            'wir suchen uns das beste Ziel.
            For I = 0 To Ziele.Length - 1
                Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Ziele(I).X, Ziele(I).Y, Schlachtfeld)
                If Sichtfeld(Ziele(I).X, Ziele(I).Y, Schlachtfeld) = True Then
                    Dim Damage As Single = 0
                    If E.Leben - Gebaeude.Schaden * 10 < 1 Then
                        Damage = E.Leben
                    Else
                        Damage = Gebaeude.Schaden * 10
                    End If
                    Dim MomGeldschaden As Integer = E.Kosten * Damage * Objektverwalter.Spielfeld.Spieler(E.Spieler).Teurungsrate(E, Gebaeude.Rechteck.X, Gebaeude.Rechteck.Y)
                    If MomGeldschaden > Geldschaden Then
                        Geldschaden = MomGeldschaden
                        BestesZiel = I
                    ElseIf MomGeldschaden = Geldschaden And Zufallszahl(0, 1) = 1 Then
                        Geldschaden = MomGeldschaden
                        BestesZiel = I
                    End If
                End If
            Next
            If BestesZiel >= 0 Then
                Return Ziele(BestesZiel)
            Else
                Return New Point(-1, -1)
            End If
        Else
            Return New Point(-1, -1)
        End If
    End Function
    ''' <summary>
    ''' Gibt den Ort zurueck, wo wir den meisten Geldschaden mit einer Rakete verursachen wuerden.
    ''' </summary>
    ''' <param name="Radius"></param>
    ''' <param name="Schaden"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetBestenEinschlagsOrt(ByVal Radius As Integer, ByVal Schaden As Integer) As Point
        Dim MomZiel As New Point(-1, -1)
        Dim Geld As Integer = 0
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                Dim Geld2 As Integer = GetSchadeninGeld(X, Y, Schaden, Radius)
                If Geld < Geld2 Then
                    Geld = Geld2
                    MomZiel = New Point(X, Y)
                ElseIf Geld = Geld2 And Zufallszahl(0, 1) = 1 Then
                    If IsNothing(Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)) = False Then
                        Geld = Geld2
                        MomZiel = New Point(X, Y)
                    End If
                End If
            Next
        Next
        Return MomZiel
    End Function
    ''' <summary>
    ''' Gibt zurueck wie viel Schaden an dieser Stelle durch eine Rakete verursacht wuerde
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <param name="Schaden"></param>
    ''' <param name="Radius"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetSchadeninGeld(ByVal X As Integer, ByVal Y As Integer, ByVal Schaden As Integer, ByVal Radius As Integer) As Integer
        Dim Geld As Integer = 0
        Dim Kreis(,) As Integer = Kreisfunktion(Radius)
        For X1 = 0 To Kreis.GetLength(0) - 1
            For Y1 = 0 To Kreis.GetLength(1) - 1
                If Kreis(X1, Y1) >= 0 Then
                    If Objektverwalter.Spielfeld.OnMap(X - Radius + X1, Y - Radius + Y1) Then
                        If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld)) = False Then
                            Dim VerlorenesLeben As Integer = Schaden
                            If VerlorenesLeben - Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).getKP > 0 Then
                                If Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).getKP > 1 Then
                                    VerlorenesLeben = Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).getKP
                                End If
                            End If
                            If Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).Spieler).Team = Objektverwalter.Spielfeld.AktuellerSpieler.Team Then
                                Geld -= Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).Kosten * VerlorenesLeben / 10 * 3
                            Else
                                Geld += Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).Kosten * VerlorenesLeben / 10
                            End If
                        End If
                    End If
                End If
            Next
        Next
        Return Geld
    End Function
    ''' <summary>
    ''' Gibt zurueck welche Einheiten mit dieser Fabrik gebaut werden sollten, sodass alle Tore benutzt werden und dabei moeglichst viele Fonds ausgegeben werden.
    ''' </summary>
    ''' <param name="Fabrik"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function BestesGeldAusgebenBeiFabrik(ByVal Fabrik As GebaeudeFabrik) As String()
        Dim MomBauEinheiten() As String = New String() {"", "", ""}
        Dim MomFonds As Integer = 0
        Dim MomEinheitenZahl As Integer = 0
        Dim Fabrikfonds As Integer = Fabrik.Variablen(1).Wert
        Dim Tor1() As String = Fabrik.GetBauEinheiten(Fabrik.Rechteck.X - 1, Fabrik.Rechteck.Y + 2)
        Dim Tor2() As String = Fabrik.GetBauEinheiten(Fabrik.Rechteck.X, Fabrik.Rechteck.Y + 2)
        Dim Tor3() As String = Fabrik.GetBauEinheiten(Fabrik.Rechteck.X + 1, Fabrik.Rechteck.Y + 2)
        If Fabrikfonds > 0 Then
            'wir ueberpruefen mehrere Moeglichkeiten.
            If Tor1.Length > 0 Then
                For I = 0 To Tor1.Length - 1
                    Dim Kosten As Integer = ObjektLadeklasse.GetEinheitenkosten(Tor1(I)) * Spieler.Teurungsrate(Tor1(I), Fabrik.Rechteck.X, Fabrik.Rechteck.Y)
                    Dim EinheitenZahl As Integer = 0
                    If Kosten <= Fabrikfonds Then
                        EinheitenZahl += 1
                        Dim Kosten2 As Integer = Kosten
                        If Tor2.Length > 0 Then
                            For I2 = 0 To Tor2.Length - 1
                                Kosten2 += ObjektLadeklasse.GetEinheitenkosten(Tor2(I2)) * Spieler.Teurungsrate(Tor2(I2), Fabrik.Rechteck.X, Fabrik.Rechteck.Y)
                                If Kosten2 <= Fabrikfonds Then
                                    EinheitenZahl += 1
                                    Dim Kosten3 As Integer = Kosten2
                                    For I3 = 0 To Tor3.Length - 1
                                        Kosten3 += ObjektLadeklasse.GetEinheitenkosten(Tor3(I3)) * Spieler.Teurungsrate(Tor3(I3), Fabrik.Rechteck.X, Fabrik.Rechteck.Y)
                                        If Kosten3 <= Fabrikfonds Then
                                            EinheitenZahl += 1
                                            If MomFonds < Kosten3 And MomEinheitenZahl <= EinheitenZahl Then
                                                MomFonds = Kosten3
                                                MomEinheitenZahl = EinheitenZahl
                                                MomBauEinheiten = New String() {Tor1(I), Tor2(I2), Tor3(I3)}
                                            ElseIf MomFonds <= Kosten3 And Zufallszahl(0, 1) = 1 Then
                                                MomFonds = Kosten3
                                                MomEinheitenZahl = EinheitenZahl
                                                MomBauEinheiten = New String() {Tor1(I), Tor2(I2), Tor3(I3)}
                                            End If
                                        End If
                                    Next
                                End If
                            Next
                        Else
                            Dim Kosten3 As Integer = Kosten2
                            If Tor3.Length > 0 Then
                                For I3 = 0 To Tor3.Length - 1
                                    Kosten3 += ObjektLadeklasse.GetEinheitenkosten(Tor3(I3)) * Spieler.Teurungsrate(Tor3(I3), Fabrik.Rechteck.X, Fabrik.Rechteck.Y)
                                    If Kosten3 <= Fabrikfonds Then
                                        EinheitenZahl += 1
                                        If MomFonds < Kosten3 And MomEinheitenZahl <= EinheitenZahl Then
                                            MomFonds = Kosten3
                                            MomEinheitenZahl = EinheitenZahl
                                            MomBauEinheiten = New String() {Tor1(I), "", Tor3(I3)}
                                        ElseIf MomFonds <= Kosten3 And Zufallszahl(0, 1) = 1 Then
                                            MomFonds = Kosten3
                                            MomEinheitenZahl = EinheitenZahl
                                            MomBauEinheiten = New String() {Tor1(I), "", Tor3(I3)}
                                        End If
                                    End If
                                Next
                            Else
                                If MomFonds < Kosten3 And MomEinheitenZahl <= EinheitenZahl Then
                                    MomFonds = Kosten3
                                    MomEinheitenZahl = EinheitenZahl
                                    MomBauEinheiten = New String() {Tor1(I), "", ""}
                                ElseIf MomFonds <= Kosten3 And Zufallszahl(0, 1) = 1 Then
                                    MomFonds = Kosten3
                                    MomEinheitenZahl = EinheitenZahl
                                    MomBauEinheiten = New String() {Tor1(I), "", ""}
                                End If
                            End If
                        End If
                    End If
                Next
            Else
                Dim EinheitenZahl As Integer = 0
                Dim Kosten2 As Integer = 0
                If Tor2.Length > 0 Then
                    For I2 = 0 To Tor2.Length - 1
                        Kosten2 += ObjektLadeklasse.GetEinheitenkosten(Tor2(I2)) * Spieler.Teurungsrate(Tor2(I2), Fabrik.Rechteck.X, Fabrik.Rechteck.Y)
                        If Kosten2 <= Fabrikfonds Then
                            EinheitenZahl += 1
                            Dim Kosten3 As Integer = Kosten2
                            For I3 = 0 To Tor3.Length - 1
                                Kosten3 += ObjektLadeklasse.GetEinheitenkosten(Tor3(I3)) * Spieler.Teurungsrate(Tor3(I3), Fabrik.Rechteck.X, Fabrik.Rechteck.Y)
                                If Kosten3 <= Fabrikfonds Then
                                    EinheitenZahl += 1
                                    If MomFonds < Kosten3 And MomEinheitenZahl <= EinheitenZahl Then
                                        MomFonds = Kosten3
                                        MomEinheitenZahl = EinheitenZahl
                                        MomBauEinheiten = New String() {"", Tor2(I2), Tor3(I3)}
                                    ElseIf MomFonds <= Kosten3 And Zufallszahl(0, 1) = 1 Then
                                        MomFonds = Kosten3
                                        MomEinheitenZahl = EinheitenZahl
                                        MomBauEinheiten = New String() {"", Tor2(I2), ""}
                                    End If
                                End If
                            Next
                        End If
                    Next
                Else
                    Dim Kosten3 As Integer = Kosten2
                    If Tor3.Length > 0 Then
                        For I3 = 0 To Tor3.Length - 1
                            Kosten3 += ObjektLadeklasse.GetEinheitenkosten(Tor3(I3)) * Spieler.Teurungsrate(Tor3(I3), Fabrik.Rechteck.X, Fabrik.Rechteck.Y)
                            If Kosten3 <= Fabrikfonds Then
                                EinheitenZahl += 1
                                If MomFonds < Kosten3 And MomEinheitenZahl <= EinheitenZahl Then
                                    MomFonds = Kosten3
                                    MomEinheitenZahl = EinheitenZahl
                                    MomBauEinheiten = New String() {"", "", Tor3(I3)}
                                ElseIf MomFonds <= Kosten3 And Zufallszahl(0, 1) = 1 Then
                                    MomFonds = Kosten3
                                    MomEinheitenZahl = EinheitenZahl
                                    MomBauEinheiten = New String() {"", "", Tor3(I3)}
                                End If
                            End If
                        Next
                    End If
                End If
            End If
        End If
        Return MomBauEinheiten
    End Function
    ''' <summary>
    ''' Gibt ein Ziel fuer ein Hoellium zurueck.
    ''' </summary>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetNaehestesHoelliumZiel(ByVal Hoellium As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Point
        Dim Ziel As New Point(-1, -1)
        Dim LetzteWegkosten As Integer = -1
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                Dim Wegkosten As Integer = WSS.getBewegungspunktekosten(X, Y)
                If Wegkosten >= 0 Then
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                    If Not E Is Nothing Then
                        If Objektverwalter.Spielfeld.Spieler(E.Spieler).Team <> Spieler.Team Then
                            If LetzteWegkosten < 0 Then
                                LetzteWegkosten = Wegkosten
                                Ziel = New Point(X, Y)
                            ElseIf Wegkosten < LetzteWegkosten Then
                                LetzteWegkosten = Wegkosten
                                Ziel = New Point(X, Y)
                            ElseIf Wegkosten = LetzteWegkosten Then
                                If E.Kosten > Objektverwalter.Spielfeld.Einheiten(Ziel.X, Ziel.Y, Schlachtfeld).Kosten Then
                                    LetzteWegkosten = Wegkosten
                                    Ziel = New Point(X, Y)
                                ElseIf E.Kosten = Objektverwalter.Spielfeld.Einheiten(Ziel.X, Ziel.Y, Schlachtfeld).Kosten And Zufallszahl(0, 1) = 1 Then
                                    LetzteWegkosten = Wegkosten
                                    Ziel = New Point(X, Y)
                                End If
                            End If
                        End If
                    End If
                End If
            Next
        Next
        Return Ziel
    End Function
    ''' <summary>
    ''' Gibt zurueck welche Infanteristen von diesem Gebaeude gebaut werden koennen.
    ''' </summary>
    ''' <param name="BauGebaeude"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetBuildInfis(ByVal BauGebaeude As ObjektGebaeude) As String()
        Dim Infis As New Stack(Of String)
        Dim BListe As String() = BauGebaeude.GetBaulisteThisPlayer
        For I = 0 To BListe.Length - 1
            If ObjektLadeklasse.NewEinheit(BListe(I), 1, -1, -1).KannBesetzen = True Then
                If BauGebaeude.CanBuildUnit(BListe(I)) = True Then
                    Infis.Push(BListe(I))
                End If
            End If
        Next
        Return Infis.ToArray
    End Function
    ''' <summary>
    ''' Gibt zurueck welche Infanteristen von diesem Gebaeude gebaut werden koennen.
    ''' </summary>
    ''' <param name="BauGebaeude"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetBuildInfis(ByVal BauGebaeude As ObjektGebaeude, ByVal Prueffonds As Integer) As String()
        Dim Infis As New Stack(Of String)
        Dim BListe As String() = BauGebaeude.GetBaulisteThisPlayer
        For I = 0 To BListe.Length - 1
            If ObjektLadeklasse.NewEinheit(BListe(I), 1, -1, -1).KannBesetzen = True Then
                If BauGebaeude.CanBuildUnit(BListe(I), Prueffonds) = True Then
                    Infis.Push(BListe(I))
                End If
            End If
        Next
        Return Infis.ToArray
    End Function
    ''' <summary>
    ''' Berechnet wie viele Zuege wir braeuchten um unser Ziel zu erreichen.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <param name="Ziel"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function CalculateZugDauer(ByVal Einheit As ObjektEinheit, ByVal WSS As Wegsuchsystem, ByVal Ziel As Point) As Integer
        Dim Bew As Integer = Einheit.GetMovementRange
        If Bew <= 0 Then
            Return -1
        End If

        Dim Dau As Integer = WSS.getBewegungspunktekosten(Ziel.X, Ziel.Y)
        If Dau < 0 Then Return -1
        Dim R As Integer = 0
        Dim Tage As Integer = Math.DivRem(Dau, Bew, R)
        If R > 0 Then
            Tage += 1
        End If
        Return Tage
    End Function
    ''' <summary>
    ''' Berechnet wie viele Zuege wir braeuchten um unser Ziel zu erreichen.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function CalculateZugDauer(ByVal Einheit As ObjektEinheit, ByVal BewKosten As Integer) As Integer
        If BewKosten < 0 Then Return -1
        Dim Bew As Integer = Einheit.GetMovementRange
        If Bew <= 0 Then
            Return -1
        End If

        Dim R As Integer = 0
        Dim Tage As Integer = Math.DivRem(BewKosten, Bew, R)
        If R > 0 Then
            Tage += 1
        End If
        Return Tage
    End Function
    ''' <summary>
    ''' Ueberprueft ob wenn wir die Einheit bauen sie sich bewegen kann.
    ''' UV
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function CanMoveAfterBuilding(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer) As Boolean
        Einheit.Spieler = Objektverwalter.Spielfeld.CurrentAI.Spieler.Spieler
        Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld).Gebaeude
        If G IsNot Nothing Then
            For I = 0 To G.CanMoveAfterBuilding.Count - 1
                If G.CanMoveAfterBuilding(I).Name = Einheit.EinheitenID Then
                    If G.CanMoveAfterBuilding(I).Wert > 0 Then
                        Return True
                    Else
                        Return False
                    End If
                End If
            Next
        End If
        Dim WSS As New Wegsuchsystem(Einheit, X, Y, Schlachtfeld, , False)
        If WSS.WegsuchenDauer(Einheit.GetMovementRange + 1) Then
            G.CanMoveAfterBuilding.Add(New ObjektGebaeude.Variable(Einheit.EinheitenID, 1))
            Return True
        End If
        G.CanMoveAfterBuilding.Add(New ObjektGebaeude.Variable(Einheit.EinheitenID, -1))
        Return False
    End Function
    ''' <summary>
    ''' Mal sehen ob die Einheit einen Gegner Angreifen kann.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function CanAttackAfterBuilding(ByVal Einheit As ObjektEinheit) As Boolean
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If Not E Is Nothing Then
                    If E.GetSpieler.Team <> Spieler.Team Then
                        If Einheit.IsAttackable(E, False, False) Then
                            Return True
                        End If
                    End If
                End If
            Next
        Next
        Return False
    End Function
    ''' <summary>
    ''' Gibt zurueck ob dieses Gebaeude Infis bauen kann.
    ''' </summary>
    ''' <param name="BauGebaeude"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function CanBuildInfi(ByVal BauGebaeude As ObjektGebaeude) As Boolean
        If BauGebaeude.CanBuildUnit("INF") Or BauGebaeude.CanBuildUnit("SSIEINHEIT") Or BauGebaeude.CanBuildUnit(MovementSorts.Mech.ToString.ToUpper) Then
            Return True
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Gibt zurueck ob das Feld von einer bestimmten Einheit beschossen werden kann.
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <param name="BeschussArt"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function IsBeschussFeldVon(ByVal X As Integer, ByVal Y As Integer, ByVal BeschussArt As BeschussArten) As Boolean
        Return GetBoolean(Beschussfelder(X, Y))(BeschussArt)
    End Function
    ''' <summary>
    ''' Die KI zieht auf der anderen Schlacht.
    ''' </summary>
    ''' <remarks></remarks>
    Protected Overridable Sub Schlachtwechsel(ByVal Sortieren As EinheitenSortierKriterien)
        While BackbufferSpiel.GetBufferLength > 0 And Objektverwalter.Spielfeld.Animationen.Length > 0
            Threading.Thread.Sleep(ThreadSleepTime)
        End While

        If Objektverwalter.Spielfeld.Regeln.Luftschlacht = True Then
            'Sorgt fuer einen Schlachtwechsel der KI.
            If Schlachtfeld = ObjektSpielfeld.Bodenschlacht Then
                Schlachtfeld = ObjektSpielfeld.Luftschlacht
            Else
                Schlachtfeld = ObjektSpielfeld.Bodenschlacht
            End If

            Objektverwalter.Spielfeld.SchlachtWechseln()
            GetAllUnits(Sortieren)
            GetAllBuildings()
            CreateSicht(Sichtfeld, Spieler)
            GetBeschussfelder()
        End If
    End Sub
    ''' <summary>
    ''' Also los!
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function ZumNaehestenHQZiehen(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Point
        Dim Z As Point = New Point(-1, -1)
        Dim Distanz As Integer = -1
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                If Not Objektverwalter.Spielfeld.Landschaften(X, Y, ObjektSpielfeld.Bodenschlacht).Hidden Then
                    Dim HQ As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X, Y, ObjektSpielfeld.Bodenschlacht).Gebaeude
                    If HQ IsNot Nothing Then
                        If HQ.Angriff = ObjektGebaeude.Angriffe.HQ Then
                            If HQ.Spieler > 0 Then
                                If HQ.GetSpieler.Team <> Einheit.GetSpieler.Team Then
                                    Dim D As Integer = WSS.getBewegungspunktekosten(X, Y, ObjektSpielfeld.Bodenschlacht)
                                    If D > 0 Then
                                        If Distanz < 0 Then
                                            Distanz = D
                                            Z = New Point(X, Y)
                                        ElseIf D < Distanz Then
                                            Distanz = D
                                            Z = New Point(X, Y)
                                        ElseIf D = Distanz And Zufallszahl(0, 2) = 0 Then
                                            Distanz = D
                                            Z = New Point(X, Y)
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    End If
                End If
            Next
        Next
        Return Z
    End Function
    Protected MustOverride Function CalculateRealZiel(ByRef WSS As Wegsuchsystem, ByVal Ziel As Point, ByVal Einheit As ObjektEinheit, ByRef Opfer As Point) As Point
    ''' <summary>
    ''' Moves troops on productions away.
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub TruppenWegZiehen()
        While MomentaneEinheit < Einheiten.Length
            Dim Einheit As ObjektEinheit = Einheiten(MomentaneEinheit)
            If Einheit.HatsichBewegt = False And Einheit.Leben > 0 Then
                Dim Gebaeude As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(Einheit.X, Einheit.Y, Schlachtfeld).Gebaeude
                If Not Gebaeude Is Nothing Then
                    If Gebaeude.GetBauliste(Gebaeude.Spieler).Length > 0 And Spieler.Team = Objektverwalter.Spielfeld.Spieler(Gebaeude.Spieler).Team And Gebaeude.Spieler > 0 Then
                        Dim WSS As New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, -1)
                        Dim Ziele As Point() = GetFreeFelder(Einheit, WSS, True)
                        If Ziele.Length > 0 Then
                            Einheitauswaehlen(Einheit, Ziele(Zufallszahl(0, Ziele.Length - 1)), KIModiExtern.Warten, Nothing, WSS, 4)
                        End If
                    End If
                End If
            End If
            MomentaneEinheit += 1
        End While
        MomentaneEinheit = 0
    End Sub
#Region "Gebaeude Angriff durch Einheiten"
    ''' <summary>
    ''' Gibt ein Gebaeude zurueck das von dieser Einheit von der momentanen Position zurueck.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns>Gibt (-1,-1) zurueck wenn kein Opfer gefunden</returns>
    ''' <remarks></remarks>
    Protected Function GetBestesNahkampfGebaeude(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Point2
        If Einheit.CanAttackBuilding Then
            Dim Opfer() As Point2 = GetAllNahKampfGebaeudefelder(Einheit, WSS)
            If Opfer.Length > 0 Then
                Dim MomentanesOpfer As Integer = Zufallszahl(0, Opfer.Length - 1)
                If MomentanesOpfer < 0 Then
                    Return New Point2(New Point(-1, -1), New Point(-1, -1))
                Else
                    Return Opfer(MomentanesOpfer)
                End If
            Else
                Return New Point2(New Point(-1, -1), New Point(-1, -1))
            End If
        Else
            Return New Point2(New Point(-1, -1), New Point(-1, -1))
        End If
    End Function
    ''' <summary>
    ''' Gibt alle Felder zurueck die in diesem Zug per Nahkampf erreicht werden koennen mit Gebaeude drauf.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetAllNahKampfGebaeudefelder(ByVal Einheit As ObjektEinheit, Optional ByRef WSS As Wegsuchsystem = Nothing) As Point2()
        Dim Felder As New Stack(Of Point2)
        If Not Einheit.Waffe1 = "Keine" Or Einheit.MinimaleReichweite = 1 Then
            'Wir haben eine Nahkampfeinheit
            Dim Bewegunspunkte As Integer = Einheit.GetMovementRange
            If WSS Is Nothing Then
                If Bewegunspunkte <= Einheit.Treibstoff Then
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
                ElseIf Einheit.Treibstoff = -1 Then
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Bewegunspunkte)
                Else
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Einheit.Treibstoff)
                End If
            End If
            For Y1 = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                For X1 = 0 To Objektverwalter.Spielfeld.Breite - 1
                    Dim Kosten As Integer = WSS.getBewegungspunktekosten(X1, Y1)
                    Dim neuerPunkt As Point = New Point(X1, Y1)
                    If Kosten >= 0 And Kosten <= Bewegunspunkte Then
                        If Objektverwalter.Spielfeld.OnMap(neuerPunkt.X, neuerPunkt.Y) Then
                            If IsFeldLeer(neuerPunkt.X, neuerPunkt.Y, Einheit) = True Then
                                GetNahAngriffsGebaeudeFelderVonFeld(Einheit, neuerPunkt, Felder)
                            End If
                        End If
                    ElseIf Objektverwalter.Spielfeld.OnMap(neuerPunkt.X, neuerPunkt.Y) Then
                        Dim X2 As Integer = X1
                        Dim Y2 As Integer = Y1
                        For I = 0 To 3
                            Select Case I
                                Case 0
                                    X2 -= 1
                                Case 1
                                    X2 += 1
                                    Y2 -= 1
                                Case 2
                                    X2 += 1
                                    Y2 += 1
                                Case 3
                                    X2 -= 1
                                    Y2 += 1
                            End Select
                            If Objektverwalter.Spielfeld.OnMap(X2, Y2) Then
                                Kosten = WSS.getBewegungspunktekosten(X2, Y2)
                                Dim P2 As New Point(X2, Y2)
                                If Kosten >= 0 And Kosten <= Bewegunspunkte Then
                                    If Objektverwalter.Spielfeld.OnMap(P2.X, P2.Y) Then
                                        If IsFeldLeer(P2.X, P2.Y, Einheit) = True Then
                                            If ExistFeld(Felder, New Point2(P2, neuerPunkt)) = False Then
                                                If Spieler.NeutraleGebaeudeAngriff = True Then
                                                    If Objektverwalter.Spielfeld.Landschaften(P2.X, P2.Y, Schlachtfeld).Leben > 0 Then
                                                        Felder.Push(New Point2(neuerPunkt, P2))
                                                    Else
                                                        Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(P2.X, P2.Y, Schlachtfeld).Gebaeude
                                                        If Not G Is Nothing Then
                                                            If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                                                If G.GetKP(P2.X, P2.Y, False) > 0 Then
                                                                    Felder.Push(New Point2(neuerPunkt, P2))
                                                                End If
                                                            End If
                                                        End If
                                                    End If
                                                Else
                                                    Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(P2.X, P2.Y, Schlachtfeld).Gebaeude
                                                    If Not G Is Nothing Then
                                                        If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                                            If G.GetKP(P2.X, P2.Y, False) > 0 Then
                                                                Felder.Push(New Point2(neuerPunkt, P2))
                                                            End If
                                                        End If
                                                    End If
                                                End If
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        Next
                    End If
                Next
            Next
        End If
        Return Felder.ToArray
    End Function
    ''' <summary>
    ''' Gibt die Felder zurueck die von diesem Feld aus angegriffen werden koennen
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="neuerPunkt"></param>
    ''' <param name="Felder"></param>
    ''' <remarks></remarks>
    Protected Sub GetNahAngriffsGebaeudeFelderVonFeld(ByVal Einheit As ObjektEinheit, ByVal neuerPunkt As Point, ByRef Felder As Stack(Of Point2))
        Dim X2 As Integer = neuerPunkt.X
        Dim Y2 As Integer = neuerPunkt.Y
        For I = 0 To 3
            Select Case I
                Case 0
                    X2 -= 1
                Case 1
                    X2 += 1
                    Y2 -= 1
                Case 2
                    X2 += 1
                    Y2 += 1
                Case 3
                    X2 -= 1
                    Y2 += 1
            End Select
            If Objektverwalter.Spielfeld.OnMap(X2, Y2) Then
                Dim P2 As New Point(X2, Y2)
                If Sichtfeld(P2.X, P2.Y, Schlachtfeld) = True Then
                    If ExistFeld(Felder, New Point2(neuerPunkt, P2)) = False Then
                        If Spieler.NeutraleGebaeudeAngriff = True Then
                            If Objektverwalter.Spielfeld.Landschaften(P2.X, P2.Y, Schlachtfeld).Leben > 0 Then
                                Felder.Push(New Point2(neuerPunkt, P2))
                            Else
                                Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(P2.X, P2.Y, Schlachtfeld).Gebaeude
                                If Not G Is Nothing Then
                                    If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                        If G.GetKP(P2.X, P2.Y, False) > 0 Then
                                            Felder.Push(New Point2(neuerPunkt, P2))
                                        End If
                                    End If
                                End If
                            End If
                        Else
                            Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(P2.X, P2.Y, Schlachtfeld).Gebaeude
                            If Not G Is Nothing Then
                                If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                    If G.GetKP(P2.X, P2.Y, False) > 0 Then
                                        Felder.Push(New Point2(neuerPunkt, P2))
                                    End If
                                End If
                            End If
                        End If
                    End If
                End If
            End If
        Next
    End Sub
    ''' <summary>
    ''' Gibt das beste Opfer dieser Einheit von der momentanen Position zurueck.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns>Gibt (-1,-1) zurueck wenn kein Opfer gefunden</returns>
    ''' <remarks></remarks>
    Protected Function GetBestesFernkampfGebaeude(ByVal Einheit As ObjektEinheit) As Point
        If Einheit.CanAttackBuilding Then
            Dim Opfer() As Point = GetAllFernKampfGebaeudeFelder(Einheit, Einheit.X, Einheit.Y)
            If Opfer.Length > 0 Then
                Return Opfer(Zufallszahl(0, Opfer.Length - 1))
            Else
                Return New Point(-1, -1)
            End If
        Else
            Return New Point(-1, -1)
        End If
    End Function
    ''' <summary>
    ''' Gibt alle Fernkampffelder zurueck die von einem Punkt beschossen werden koennen
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetAllFernKampfGebaeudeFelder(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer) As Point()
        Dim Felder As New Stack(Of Point)
        If Einheit.MaximaleReichweite > 1 Then
            Dim MaximaleReichweite As Integer = Einheit.MaximaleReichweite
            Dim MinimaleReichweite As Integer = Einheit.MinimaleReichweite
            Dim Kreis(,) As Integer = Kreisfunktion(MaximaleReichweite)
            If MaximaleReichweite > 1 Then
                For X1 = 0 To MaximaleReichweite * 2
                    For Y1 = 0 To MaximaleReichweite * 2
                        If Kreis(X1, Y1) >= MinimaleReichweite Then
                            Dim neuerPunkt As Point = New Point(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1)
                            If Objektverwalter.Spielfeld.OnMap(neuerPunkt.X, neuerPunkt.Y) Then
                                If Felder.Contains(neuerPunkt) = False Then
                                    If Spieler.NeutraleGebaeudeAngriff = True Then
                                        If Objektverwalter.Spielfeld.Landschaften(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Leben > 0 Then
                                            Felder.Push(neuerPunkt)
                                        Else
                                            Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Gebaeude
                                            If Not G Is Nothing Then
                                                If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                                    If G.GetKP(neuerPunkt.X, neuerPunkt.Y, False) > 0 Then
                                                        Felder.Push(neuerPunkt)
                                                    End If
                                                End If
                                            End If
                                        End If
                                    Else
                                        Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Gebaeude
                                        If Not G Is Nothing Then
                                            If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                                If G.GetKP(neuerPunkt.X, neuerPunkt.Y, False) > 0 Then
                                                    Felder.Push(neuerPunkt)
                                                End If
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    Next
                Next
            End If
        End If
        Return Felder.ToArray
    End Function
    ''' <summary>
    ''' Gibt eines der naehesten Felder zurueck von dem aus ohne Bewegung in der naechsten Runde angegriffen werden koennte.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetNaehestesFernkampfGebaeudefeld(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Point
        Dim Ziel As New Point(-1, -1)
        Dim MomentaneWegkosten As Integer = -1
        If Einheit.CanAttackBuilding Then
            If Einheit.MaximaleReichweite > 1 Then
                If WSS Is Nothing Then
                    WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, -1)
                End If
                For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                    For Y = 0 To Objektverwalter.Spielfeld.Hoehe
                        If WSS.getBewegungspunktekosten(X, Y) >= 0 Then
                            If IsFeldLeer(X, Y, Einheit) = True Then
                                'Wir koennen das Feld erreichen
                                If KannFernkampfGebaeudeGemachtWerden(Einheit, X, Y) = True Then
                                    If WSS.getBewegungspunktekosten(X, Y) < MomentaneWegkosten Then
                                        MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                        Ziel = New Point(X, Y)
                                    ElseIf WSS.getBewegungspunktekosten(X, Y) = MomentaneWegkosten And Zufallszahl(0, 1) = 1 Then
                                        MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                        Ziel = New Point(X, Y)
                                    ElseIf MomentaneWegkosten = -1 Then
                                        MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                        Ziel = New Point(X, Y)
                                    End If
                                End If
                            End If
                        End If
                    Next
                Next
            End If
        End If
        Return Ziel
    End Function
    ''' <summary>
    ''' Gibt an ob von diesem Feld aus ein Fernkampf ausgefuehrt werden kann.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function KannFernkampfGebaeudeGemachtWerden(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer) As Boolean
        If Einheit.MaximaleReichweite > 1 Then
            Dim MaximaleReichweite As Integer = Einheit.MaximaleReichweite
            Dim MinimaleReichweite As Integer = Einheit.MinimaleReichweite
            Dim Stelle As Integer = Array.IndexOf(Objektverwalter.Spielfeld.AktuellerSpieler.KOS(0).WetterartfuerSenker, Objektverwalter.Spielfeld.Regeln.Wetter)
            Dim Kreis(,) As Integer = Kreisfunktion(MaximaleReichweite)
            If MaximaleReichweite > 1 Then
                For X1 = 0 To MaximaleReichweite * 2
                    For Y1 = 0 To MaximaleReichweite * 2
                        If Kreis(X1, Y1) >= MinimaleReichweite Then
                            Dim neuerPunkt As Point = New Point(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1)
                            If Objektverwalter.Spielfeld.OnMap(neuerPunkt.X, neuerPunkt.Y) Then
                                If Spieler.NeutraleGebaeudeAngriff = True Then
                                    If Objektverwalter.Spielfeld.Landschaften(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Leben > 0 Then
                                        Return True
                                    Else
                                        Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Gebaeude
                                        If Not G Is Nothing Then
                                            If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                                If G.GetKP(neuerPunkt.X, neuerPunkt.Y, False) > 0 Then
                                                    Return True
                                                End If
                                            End If
                                        End If
                                    End If
                                Else
                                    Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Gebaeude
                                    If Not G Is Nothing Then
                                        If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                            If G.GetKP(neuerPunkt.X, neuerPunkt.Y, False) > 0 Then
                                                Return True
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    Next
                Next
            End If
        End If
        Return False
    End Function
    ''' <summary>
    ''' Gibt das Feld zurueck auf das wir ziehen sollten um moeglichst bald angreifen zu koennen. Mit einer Nahkampfeinheit
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetNaehestenNahkampfGebaeude(ByVal Einheit As ObjektEinheit, Optional ByRef WSS As Wegsuchsystem = Nothing) As Point
        Dim Ziel As New Point(-1, -1)
        Dim MomentaneWegkosten As Integer = -1
        If Einheit.MinimaleReichweite = 1 Then
            If WSS Is Nothing Then
                WSS = New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, -1)
            End If
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe
                    If WSS.getBewegungspunktekosten(X, Y) >= 0 Then
                        If IsFeldLeer(X, Y, Einheit) Then
                            'Wir koennen das Feld erreichen
                            If KannNahkampfGebaeudevonFeldgemachtwerden(Einheit, X, Y) = True Then
                                If WSS.getBewegungspunktekosten(X, Y) < MomentaneWegkosten Then
                                    MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                    Ziel = New Point(X, Y)
                                ElseIf WSS.getBewegungspunktekosten(X, Y) = MomentaneWegkosten And Zufallszahl(0, 1) = 1 Then
                                    MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                    Ziel = New Point(X, Y)
                                ElseIf MomentaneWegkosten = -1 Then
                                    MomentaneWegkosten = WSS.getBewegungspunktekosten(X, Y)
                                    Ziel = New Point(X, Y)
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        End If
        Return Ziel
    End Function
    ''' <summary>
    ''' Gibt an ob von diesem Feld aus ein Fernkampf ausgefuehrt werden kann.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function KannNahkampfGebaeudevonFeldgemachtwerden(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer) As Boolean
        If Einheit.MaximaleReichweite > 1 Then
            Dim MaximaleReichweite As Integer = Einheit.MaximaleReichweite
            Dim MinimaleReichweite As Integer = Einheit.MinimaleReichweite
            If MaximaleReichweite > 1 Then
                Dim Kreis(,) As Integer = Kreisfunktion(MaximaleReichweite)
                For X1 = 0 To MaximaleReichweite * 2
                    For Y1 = 0 To MaximaleReichweite * 2
                        If Kreis(X1, Y1) >= MinimaleReichweite Then
                            Dim neuerPunkt As Point = New Point(X - MaximaleReichweite + X1, Y - MaximaleReichweite + Y1)
                            If Objektverwalter.Spielfeld.OnMap(neuerPunkt.X, neuerPunkt.Y) Then
                                If Spieler.NeutraleGebaeudeAngriff = True Then
                                    If Objektverwalter.Spielfeld.Landschaften(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Leben > 0 Then
                                        Return True
                                    Else
                                        Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Gebaeude
                                        If Not G Is Nothing Then
                                            If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                                If G.GetKP(neuerPunkt.X, neuerPunkt.Y, False) > 0 Then
                                                    Return True
                                                End If
                                            End If
                                        End If
                                    End If
                                Else
                                    Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld).Gebaeude
                                    If Not G Is Nothing Then
                                        If Objektverwalter.Spielfeld.Spieler(G.Spieler).Team <> Spieler.Team Then
                                            If G.GetKP(neuerPunkt.X, neuerPunkt.Y, False) > 0 Then
                                                Return True
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    Next
                Next
            End If
        End If
        Return False
    End Function
    ''' <summary>
    ''' Lohnt es sich ueberhaupt Landeboote zu bauen?
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function IsLandeBootBauSinnvoll() As Boolean
        For Each G In Gebaeude
            If TypeOf G Is GebaeudeHafen Then
                If G.Spieler = Spieler.Spieler Then
                    For Each Unit In Objektverwalter.Spielfeld.Einheiten
                        If Unit IsNot Nothing Then
                            If Unit.Spieler = Spieler.Spieler Then
                                If Unit.CanAttack Then
                                    Dim WSS As New Wegsuchsystem(Unit, , False, Wegsuchsystem.SuchartenEinheiten.AlleEinheitenIgnorieren)
                                    If WSS.Wegsuchen(True, Unit.KannBesetzen) < 0 Then
                                        Return True
                                    End If
                                End If
                            End If
                        End If
                    Next
                    Return False
                End If
            End If
        Next
        Return False
    End Function
    ''' <summary>
    ''' Entfernt alle Gebaeude, die nichts bauen koennen
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub TrimGebaeude()
        Dim G2 As New Stack(Of ObjektGebaeude)
        For I = 0 To Gebaeude.Length - 1
            If Gebaeude(I).GetBaulisteThisPlayer.Length > 0 Then
                G2.Push(Gebaeude(I))
            End If
        Next
        Gebaeude = G2.ToArray
    End Sub
#End Region
#End Region
#Region "Extern Gezogene Truppen"
    ''' <summary>
    ''' Zieht die Einheiten welche die KI nicht steuern soll
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub ExternGesteurteEinheiten()
        MoveAIUnits()
        Dim I As Integer = 0
        While I < Spieler.ExternGezogeneEinheiten.Length
            Dim E As ObjektEinheit = Spieler.ExternGezogeneEinheiten(I).Einheit
            If ExistUnit(E) Then
                If E.HatsichBewegt = False Then
                    Select Case Spieler.ExternGezogeneEinheiten(I).Befehl
                        Case ObjektSpieler.ExternGezogeneEinheit.Befehle.WartenBisAngriff

                            If Not E Is Nothing Then

                                If E.HatsichBewegt = False Then
                                    If E.Treibstoff > 0 Then
                                        If E.MaximaleReichweite > 1 Then
                                            Dim WSS As Wegsuchsystem = CreateWSS(E)
                                            'OH je  das wird noch komplikate
                                            If Spieler.KOS(0).MoveandFire = True And Spieler.KOS(0).FireandMove = True Then
                                                Dim Feld As Point = GetBestesFernkampfOpfer(E)
                                                If Feld.X >= 0 Then
                                                    Einheitauswaehlen(E, New Point(E.X, E.Y), KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Feld.X, Feld.Y, Schlachtfeld), WSS)
                                                    DoNaechsterBefehlExternGezogen(I)
                                                    Dim Felder As Point2 = GetBestesFernkampfFeldmitBewegung(E, WSS)
                                                    If Felder.Point1.X >= 0 And Felder.Point2.X >= 0 Then
                                                        'So wir haben ein Opfer.
                                                        NaechsterBefehl(Felder.Point1, Objektverwalter.Spielfeld.Einheiten(Felder.Point2.X, Felder.Point2.Y, Schlachtfeld), KIModiExtern.Angriff, WSS, 4)
                                                    End If
                                                Else
                                                    Dim Felder As Point2 = GetBestesFernkampfFeldmitBewegung(E, WSS)
                                                    If Felder.Point1.X >= 0 And Felder.Point2.X >= 0 Then
                                                        'So wir haben ein Opfer.
                                                        Einheitauswaehlen(E, Felder.Point1, KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Felder.Point2.X, Felder.Point2.Y, Schlachtfeld), WSS)
                                                        DoNaechsterBefehlExternGezogen(I)
                                                    End If
                                                End If
                                                EinheitAbwaehlen()
                                            ElseIf Spieler.KOS(0).MoveandFire = True Then
                                                'Ein Angriff ziehen und Feuern wie beim Nahkampf
                                                Dim Felder As Point2 = GetBestesFernkampfFeldmitBewegung(E, WSS)
                                                If Felder.Point1.X >= 0 And Felder.Point2.X >= 0 Then
                                                    'So wir haben ein Opfer.
                                                    Einheitauswaehlen(E, Felder.Point1, KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Felder.Point2.X, Felder.Point2.Y, Schlachtfeld), WSS)
                                                    DoNaechsterBefehlExternGezogen(I)
                                                End If
                                            ElseIf Spieler.KOS(0).FireandMove = True Then
                                                'Wir suchen uns ein Opfer
                                                Dim Feld As Point = GetBestesFernkampfOpfer(E)
                                                If Feld.X >= 0 Then
                                                    Einheitauswaehlen(E, New Point(E.X, E.Y), KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Feld.X, Feld.Y, Schlachtfeld), WSS)
                                                    DoNaechsterBefehlExternGezogen(I)
                                                End If
                                                'wir haben unser Opfer angegriffen jetzt sollten wir die Einheit noch ziehen.
                                                WSS = New Wegsuchsystem(E, E.X, E.Y, E.GetMap, -1)
                                                Dim Ziel As Point = GetNaehestesFernkampffeld(E, WSS)
                                                If Ziel.X >= 0 Then
                                                    If Objektverwalter.Spielfeld.AktuelleEinheit Is Nothing Then
                                                        Einheitauswaehlen(E, New Point(E.X, E.Y), KIModiExtern.Warten, Nothing, WSS)
                                                        DoNaechsterBefehlExternGezogen(I)
                                                    Else
                                                        NaechsterBefehl(Ziel, Nothing, KIModiExtern.Warten, WSS, 4)
                                                    End If
                                                Else
                                                    EinheitAbwaehlen()
                                                End If
                                            Else
                                                'Das ist mir die liebste und einfachst Situation Uff.
                                                Dim Feld As Point = GetBestesFernkampfOpfer(E)
                                                If Feld.X >= 0 Then
                                                    Einheitauswaehlen(E, New Point(E.X, E.Y), KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Feld.X, Feld.Y, Schlachtfeld), WSS, 4)
                                                    DoNaechsterBefehlExternGezogen(I)
                                                End If
                                            End If
                                        ElseIf E.MinimaleReichweite = 1 Or E.Waffe1 = "Keine" Then
                                            'Wir lassen sie einen Nahkampf machen.
                                            Dim WSS As Wegsuchsystem = CreateWSS(E)
                                            Dim Feld As Point2 = GetBestesNahkampfOpfer(E, WSS)
                                            If Feld.Point1.X >= 0 And Feld.Point2.X >= 0 Then
                                                Einheitauswaehlen(E, Feld.Point1, KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Feld.Point2.X, Feld.Point2.Y, Schlachtfeld), WSS, 4)
                                                DoNaechsterBefehlExternGezogen(I)
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        Case ObjektSpieler.ExternGezogeneEinheit.Befehle.Bauen 'Hier wollten wir die KI dazu bringen an bestimmten Orten ein Gebaeude zu bauen!

                        Case ObjektSpieler.ExternGezogeneEinheit.Befehle.Heilen
                            If E.getKP >= 9 Then
                                DoNaechsterBefehlExternGezogen(I)
                            Else
                                Dim WSS As Wegsuchsystem = CreateWSS(E)
                                Dim Gezogen As Boolean = False
                                'Mal sehen ob wir klug angreifen koennen.
                                If E.MaximaleReichweite > 1 Then
                                    Dim Feld As Point = GetBestesFernkampfOpfer(E)

                                    If Feld.X >= 0 Then
                                        Einheitauswaehlen(E, New Point(E.X, E.Y), KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Feld.X, Feld.Y, Schlachtfeld), WSS, 4)
                                        Gezogen = True
                                    End If
                                End If
                                If E.MinimaleReichweite = 1 Or E.Waffe1 = "Keine" And Not Gezogen Then
                                    'Nahkaempfer suchen ein Opfer, wo sie den meisten Schaden machen aber weniger als 2 TP Schaden erleiden.
                                    Dim Ziel As Point2 = GetBestesNahkampfOpferExtern(E, WSS, GetAllNahKampffelder(E, True, WSS))
                                    'Es ist eine Nahkampf Einheit mit einem Ziel
                                    If Ziel.Point1.X >= 0 Then
                                        Einheitauswaehlen(E, Ziel.Point1, KIModiExtern.Angriff, New EinheitAmphibienpanzer(0, Ziel.Point2.X, Ziel.Point2.Y), WSS, 4)
                                    End If
                                End If
                                If Not Gezogen Then
                                    Einheitauswaehlen(E, New Point(E.X, E.Y), KIModiExtern.Warten, Nothing, WSS, 2) 'Die Einheit wartet weiter.
                                End If
                            End If
                    End Select
                End If
            Else
                RemoveEinheit(I)
            End If
            I += 1
        End While
        KIModusIntern = KIModiIntern.Besetzen
    End Sub
    ''' <summary>
    ''' Fuehrt den naechsten Befehl aus.
    ''' </summary>
    ''' <param name="I"></param>
    ''' <remarks></remarks>
    Private Sub DoNaechsterBefehlExternGezogen(ByRef I As Integer)
        Select Case Spieler.ExternGezogeneEinheiten(I).NaechsterBefehl
            Case ObjektSpieler.ExternGezogeneEinheit.NaechsteBefehle.Entfernen
                Spieler.ExternGezogeneEinheiten(I) = Spieler.ExternGezogeneEinheiten(Spieler.ExternGezogeneEinheiten.Length - 1)
                Array.Resize(Spieler.ExternGezogeneEinheiten, Spieler.ExternGezogeneEinheiten.Length - 1)
                I -= 1
        End Select
    End Sub
    Private Sub RemoveEinheit(ByVal I As Integer)
        Spieler.ExternGezogeneEinheiten(I) = Spieler.ExternGezogeneEinheiten(Spieler.ExternGezogeneEinheiten.Length - 1)
        Array.Resize(Spieler.ExternGezogeneEinheiten, Spieler.ExternGezogeneEinheiten.Length - 1)
        I -= 1
    End Sub
    ''' <summary>
    ''' Gibt das beste Opfer dieser Einheit von der momentanen Position zurueck.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns>Gibt (-1,-1) zurueck wenn kein Opfer gefunden</returns>
    ''' <remarks></remarks>
    Protected Function GetBestesNahkampfOpferExtern(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem, ByVal Opfer() As Point2) As Point2
        If Opfer.Length > 0 Then
            Dim MomentanesOpfer As Integer = -1
            Dim MomentanerSchaden As Single = 0
            Dim MomentaneTPDifferenz As Single = -100
            For I = 0 To Opfer.Length - 1
                Dim ZielPos As Point = Opfer(I).Point1
                'Greifen wir von einem Gebaeude aus an?
                If Objektverwalter.Spielfeld.Landschaften(ZielPos.X, ZielPos.Y, Objektverwalter.Spielfeld.MomentaneSchlacht).Gebaeude IsNot Nothing Then
                    Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(ZielPos.X, ZielPos.Y, Objektverwalter.Spielfeld.MomentaneSchlacht).Gebaeude
                    'Kann das Gebaeude uns heilen?
                    If Spieler.IsReperaturGebaeude(G.GetSpieler) Then

                        'Kann es uns Reparieren?
                        If Not G.GetBaulisteThisPlayer.Contains(Einheit.EinheitenID) Then
                            If G.Versorung Then
                                If Not ObjektLadeklasse.GetBauliste("BASIS").Contains(Einheit.EinheitenID) Then
                                    Continue For
                                End If
                            Else
                                Continue For
                            End If
                        End If


                        Dim UnserOpfer As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Opfer(I).Point2.X, Opfer(I).Point2.Y, Schlachtfeld)
                        'Wir berechnen wie viel Geldschaden wir anrichten wuerden
                        Dim TPDifferenz As Single = 0
                        Dim Schaden As Single = GetGeldschadenExternesHeilung(Einheit, Opfer(I).Point1.X, Opfer(I).Point1.Y, UnserOpfer, TPDifferenz)
                        Select Case OpferBerechnung
                            Case GeldTPAngriffsModus.NurTP
                                If TPDifferenz > MinimaleTPDifferenz Then
                                    If TPDifferenz > MomentaneTPDifferenz Then
                                        MomentaneTPDifferenz = TPDifferenz
                                        MomentanesOpfer = I
                                    ElseIf TPDifferenz = MomentaneTPDifferenz And Zufallszahl(0, 1) = 1 Then
                                        MomentaneTPDifferenz = TPDifferenz
                                        MomentanesOpfer = I
                                    End If
                                End If
                            Case GeldTPAngriffsModus.Beides
                                If TPDifferenz > MinimaleTPDifferenz Then
                                    If Schaden >= MinimalerGeldschaden Then
                                        If TPDifferenz > MomentaneTPDifferenz And Schaden > MomentanerSchaden Then
                                            MomentaneTPDifferenz = TPDifferenz
                                            MomentanerSchaden = Schaden
                                            MomentanesOpfer = I
                                        ElseIf TPDifferenz = MomentaneTPDifferenz And Schaden >= MomentanerSchaden And Zufallszahl(0, 1) = 1 Then
                                            MomentaneTPDifferenz = TPDifferenz
                                            MomentanerSchaden = Schaden
                                            MomentanesOpfer = I
                                        ElseIf TPDifferenz >= MomentaneTPDifferenz And Schaden = MomentanerSchaden And Zufallszahl(0, 1) = 1 Then
                                            MomentaneTPDifferenz = TPDifferenz
                                            MomentanerSchaden = Schaden
                                            MomentanesOpfer = I
                                        End If
                                    End If
                                End If
                            Case GeldTPAngriffsModus.NurGeld
                                If Schaden >= MinimalerGeldschaden Then
                                    If Schaden > MomentanerSchaden Then
                                        MomentanerSchaden = Schaden
                                        MomentanesOpfer = I
                                    ElseIf Schaden = MomentanerSchaden And Zufallszahl(0, 1) = 1 Then
                                        MomentanerSchaden = Schaden
                                        MomentanesOpfer = I
                                    End If
                                End If
                        End Select
                    End If
                End If
            Next
            If MomentanesOpfer < 0 Then
                Return New Point2(New Point(-1, -1), New Point(-1, -1))
            Else
                Return Opfer(MomentanesOpfer)
            End If
        Else
            Return New Point2(New Point(-1, -1), New Point(-1, -1))
        End If
    End Function
    ''' <summary>
    ''' Gibt zurueck wie gross der Geldschaden waere wenn wir von diesem Feld aus angreifen wuerden.
    ''' </summary>
    ''' <param name="Angreifer"></param>
    ''' <param name="ATKX"></param>
    ''' <param name="ATKY"></param>
    ''' <param name="Verteidiger"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetGeldschadenExternesHeilung(ByVal Angreifer As ObjektEinheit, ByVal ATKX As Integer, ByVal ATKY As Integer, ByVal Verteidiger As ObjektEinheit, ByRef TPDifferenz As Single) As Single
        Dim Glueck As Point = Spieler.GetGlueckPech(ATKX, ATKY)
        AktuelleZiel = New Point(ATKX, ATKY)
        If Gluecksfaktor > 0 Then
            Glueck.X *= Gluecksfaktor
        Else
            Glueck.X = Glueck.Y * Gluecksfaktor
        End If
        Dim OpferLeben As Single = Verteidiger.Leben
        Dim Schaden As Single = Objektverwalter.Schadensberechnung(Angreifer, ATKX, ATKY, Verteidiger.X, Verteidiger.Y, Angreifer.Leben, OpferLeben, False, True, Glueck.X, Verteidiger, False)(0)
        Glueck = Objektverwalter.Spielfeld.Spieler(Verteidiger.Spieler).GetGlueckPech(Verteidiger.X, Verteidiger.Y)
        If Gluecksfaktor > 0 Then
            Glueck.X *= Gluecksfaktor
        Else
            Glueck.X = Glueck.Y * Gluecksfaktor
        End If

        OpferLeben = Angreifer.Leben
        Dim EigenSchaden As Single = Objektverwalter.Schadensberechnung(Verteidiger, Verteidiger.X, Verteidiger.Y, ATKX, ATKY, Verteidiger.Leben - Schaden, OpferLeben, True, True, Glueck.X, Angreifer, False)(0)
        Dim Verteidigerleben As Single = Verteidiger.Leben - Schaden
        If Schaden > Verteidiger.Leben Then
            Schaden = Verteidiger.Leben
            Verteidigerleben = 0
        End If
        TPDifferenz = Schaden - EigenSchaden
        Dim GegenSchaden As Single = EigenSchaden * Angreifer.Kosten * Spieler.Teurungsrate(Angreifer, ATKX, ATKY) * EigenerEinheitenWert
        Schaden = Verteidiger.Kosten * Schaden * Objektverwalter.Spielfeld.Spieler(Verteidiger.Spieler).Teurungsrate(Verteidiger, Verteidiger.X, Verteidiger.Y)

        If GegenSchaden <= 0 Or Verteidigerleben <= 0 Then
            Schaden /= 10000
            If Schaden < MinimalerGeldschaden Then
                Schaden = MinimalerGeldschaden
            End If
        Else
            Schaden = Schaden / GegenSchaden
        End If
        If Verteidiger.MaximaleReichweite > 1 Then
            Schaden += Verteidiger.Kosten / 1000
        End If
        'Der Wert 15% des Lebens kann noch geaendert werden.
        If EigenSchaden < 15 Then
            Return Schaden
        Else
            Return -1
        End If
    End Function
#End Region
#Region "Transport System"
    ''' <summary>
    ''' Zieht die Transporter und entlaedt Einheiten.
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub TransporterZiehen(ByVal Sortieren As EinheitenSortierKriterien)
        Dim Entladen As Boolean = False
        While MomentaneEinheit < Einheiten.Length
            Dim Einheit As ObjektEinheit = Einheiten(MomentaneEinheit)
            If ExistUnit(Einheit) = True Then
                If Einheiten(MomentaneEinheit).IsUsingUnit(MinimalerTreibstoff, MinimaleMunition, MinimaleKP) = True Then
                    If Einheit.Ladung.Length > 0 Then
                        'Es ist ein Transporter, es kann hier auch passieren, dass Transporter verladen werden.
                        'Zuerst finden wir heraus ob die Einheit eine Fracht hat.
                        Dim WSS As New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, -1, False)
                        Dim Ziel As Stack(Of Point2) = GetTransporterZiel(Einheit, WSS)
                        If Ziel(0).Point1.X >= 0 Then
                            If ContainsZiel(Ziel) Then
                                If IsInfiTransporter(Einheit) And Einheit.GetGeladeneEinheitenZahl = 1 Then
                                    Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(Ziel(0).Point1.X, Ziel(0).Point1.Y, Schlachtfeld).Gebaeude
                                    If G IsNot Nothing Then
                                        If G.IsBesetzung(Einheit.Ladung(0)) Then
                                            Dim G2 As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(Ziel(0).Point2.X, Ziel(0).Point2.Y, Schlachtfeld).Gebaeude
                                            If G2 IsNot Nothing Then
                                                If G2.IsBesetzung(Einheit.Ladung(0)) Then
                                                    TransportZiehenUndEntladen(Einheit, Ziel, WSS)
                                                Else
                                                    Dim Z As Point2 = Ziel.Pop
                                                    Ziel.Push(New Point2(Z.Point2, Z.Point1))
                                                    TransportZiehenUndEntladen(Einheit, Ziel, WSS)
                                                End If
                                            Else
                                                Dim Z As Point2 = Ziel.Pop
                                                Ziel.Push(New Point2(Z.Point2, Z.Point1))
                                                TransportZiehenUndEntladen(Einheit, Ziel, WSS)
                                            End If
                                        Else
                                            TransportZiehenUndEntladen(Einheit, Ziel, WSS)
                                        End If
                                    Else
                                        TransportZiehenUndEntladen(Einheit, Ziel, WSS)
                                    End If
                                Else
                                    TransportZiehenUndEntladen(Einheit, Ziel, WSS)
                                End If
                            Else
                                Dim Ziel2 As Point = CalculateRealZiel(WSS, Ziel(0).Point1, Einheit, New Point)
                                Einheitauswaehlen(Einheit, Ziel2, KIModiExtern.Warten, Nothing, WSS, 4)
                            End If
                            Entladen = True

                        Else
                            If TransporterVerladen(Einheit) Then
                                Exit Sub
                            Else 'Einfach warten!
                                Einheitauswaehlen(Einheit, New Point(Einheit.X, Einheit.Y), KIModiExtern.Warten, Nothing, Nothing, 4)
                                EinheitGezogenVonVorneStarten()
                                Exit Sub
                            End If
                        End If
                    End If
                End If
            End If
            MomentaneEinheit += 1
        End While
        If Entladen Then
            GetAllUnits(Sortieren)
            EinheitGezogenVonVorneStarten()
            Exit Sub
        End If
    End Sub
    Private Sub TransportZiehenUndEntladen(ByVal Einheit As ObjektEinheit, ByVal Ziel As Stack(Of Point2), ByVal WSS As Wegsuchsystem)
        Dim ModusAlt As KIModiIntern = KIModusIntern
        KIModusIntern = KIModiIntern.Transproterziehen
        Dim ErsterZug As Boolean = True
        Dim BewZiel As Point = Ziel(0).Point1
        Dim Truppe As Integer = 0
        While Ziel.Count > 0
            Dim Z As Point2 = Ziel.Pop
            WSS.Ziel(Z.Point1.X, Z.Point1.Y, True, True)
            Z.Point1 = New Point(WSS.WegpunkteX(0), WSS.WegpunkteY(0))
            'Selbes Entladungsfeld
            If Z.Point1 = BewZiel Then
                'es kann entladen werden
                If Z.Point2.X >= 0 Then
                    Dim Gegner As New EinheitAmphibienpanzer(1, Z.Point2.X, Z.Point2.Y)
                    AngreiferSchaden = Truppe
                    If Einheit.HatsichBewegt = False Then
                        If ErsterZug Then
                            Einheitauswaehlen(Einheit, BewZiel, KIModiExtern.Entladen, Gegner, WSS, 4, True)
                            ErsterZug = False
                        Else
                            NaechsterBefehl(BewZiel, Gegner, KIModiExtern.Entladen, WSS, 4, False)
                        End If
                    End If
                    'Etwas reduzieren, da ja die Truppen aufruecken.
                    Truppe -= 1
                End If
            End If
            Truppe += 1
        End While
        'Fertig gezogen.
        If Objektverwalter.Spielfeld.AktuelleEinheit IsNot Nothing Then
            NaechsterBefehl(BewZiel, Nothing, KIModiExtern.Warten, WSS, 4)
        End If
        KIModusIntern = ModusAlt
    End Sub
    Protected Function TransporterVerladen(ByVal Einheit As ObjektEinheit) As Boolean
        If Not Einheit.HatsichBewegt Then
            Dim WSS As New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, -1)
            Dim Ziel As Vector3 = GetTransporter(Einheit, WSS)
            'Wir haben einen Transporter gefunden!
            If Ziel.X >= 0 Then
                If Ziel.Z >= 0 Then
                    'Wir koennen ihn erreichen!
                    If Ziel.Z = 0 Then
                        'Sogar ihn dieser Runde!
                        Einheitauswaehlen(Einheit, New Point(Ziel.X, Ziel.Y), KIModiExtern.Fracht, Nothing, WSS, 4)
                        EinheitGezogenVonVorneStarten()
                        Return True
                    Else
                        Einheitauswaehlen(Einheit, New Point(Ziel.X, Ziel.Y), KIModiExtern.Warten, Nothing, WSS, 4)
                        EinheitGezogenVonVorneStarten()
                        Return True
                    End If
                Else
                    'Leider ist er noch zu weit weg!
                    Einheitauswaehlen(Einheit, New Point(Ziel.X, Ziel.Y), KIModiExtern.Warten, Nothing, WSS, 4)
                    EinheitGezogenVonVorneStarten()
                    Return True
                End If
            Else
                If Not Einheit.HatsichBewegt Then
                    'schauen wir mal ob unter uns ein Gebaeude ist
                    Dim Gebaeude As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(Einheit.X, Einheit.Y, Schlachtfeld).Gebaeude
                    If Not Gebaeude Is Nothing Then
                        If Gebaeude.GetBaulisteThisPlayer.Length > 0 And Spieler.Team = Objektverwalter.Spielfeld.Spieler(Gebaeude.Spieler).Team Then
                            Dim Ziele As Point() = GetFreeFelder(Einheit, WSS, True)
                            If Ziele.Length > 0 Then
                                Einheitauswaehlen(Einheit, Ziele(Zufallszahl(0, Ziele.Length - 1)), KIModiExtern.Warten, Nothing, WSS, 4)
                                EinheitGezogenVonVorneStarten()
                                Return True
                            End If
                        End If
                    End If
                End If
            End If
        End If
        Return False
    End Function
    ''' <summary>
    ''' Wo hin man ziehen soll wenn wir einen Transporter haben!
    ''' </summary>
    ''' <param name="Transporter"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetTransporterZiel(ByVal Transporter As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Stack(Of Point2)
        Dim Ziel As New Stack(Of Point2)
        If Not Transporter.HatsichBewegt Then
            Dim TWegsuchsysteme As New Stack(Of Wegsuchsystem)
            If Transporter.HasLadung Then
                Dim L As ObjektLandschaft = Nothing
                'Wo sollen wir entladen?
                For Each Ladung In Transporter.Ladung
                    If Ladung IsNot Nothing Then
                        Ladung.X = -1
                        Ladung.Y = -1
                        TWegsuchsysteme.Push(New Wegsuchsystem(Ladung, , False, Wegsuchsystem.SuchartenEinheiten.AlleEinheitenIgnorieren))
                    End If
                Next
                'So zuerst das Wegsuchsystem ausbreiten
                WSS.BerechnungsStart(Transporter, -1, True)
                Dim TWSSS As Wegsuchsystem() = TWegsuchsysteme.ToArray
                'Jetzt alle Startfelder bestimmen
                For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                    For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                        If WSS.getBewegungspunktekosten(X, Y, Schlachtfeld) >= 0 Then
                            L = Objektverwalter.Spielfeld.Landschaften(X, Y, Schlachtfeld)
                            If Transporter.EntladungsUntergrund.Contains(L.getID) Then
                                L = Wegsuchsystem.getFeldRundrum(X, Y, Schlachtfeld, 1, 1, Nothing, Objektverwalter.Spielfeld)
                                Do Until L Is Nothing
                                    For Each TWSS In TWSSS
                                        If TWSS.Einheit.CanMoveOverTile(L.KooX, L.KooY, Schlachtfeld) Then
                                            If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld) Is Nothing Then
                                                Dim Start As Integer = WSS.getRundeDiskret(WSS.getBewegungspunktekosten(X, Y, Schlachtfeld), False)
                                                'Je nach Anzahl der Runden die wir brauchen um hier hin zu kommen kommt eine andere Startzahl rein!
                                                'Wir erstellen den Wegsucher und schreiben die Zeit rein!
                                                TWSS.setWegsucher(X, Y, Schlachtfeld, (Start * TWSS.Einheit.GetMovementRange) + 1)
                                            End If
                                        End If
                                    Next
                                    L = Wegsuchsystem.getFeldRundrum(X, Y, Schlachtfeld, 1, 1, L, Objektverwalter.Spielfeld)
                                Loop
                            End If
                        End If
                    Next
                Next
                Dim Z As New Stack(Of Point)
                Dim Dauer As New Stack(Of Integer)
                'Fuer jedes Wegsuchsystem dem Weg zum Feind suchen.
                For Each TWSS In TWSSS
                    If TWSS.Einheit.KannBesetzen Then
                        If TWSS.Einheit.CanAttack Then
                            Z.Push(TWSS.WegsuchenTransporter(True, True))
                            Dauer.Push(TWSS.getRundeDiskret(TWSS.getBewegungspunktekosten(Z.Peek), False))
                        Else
                            Z.Push(TWSS.WegsuchenTransporter(False, True))
                            Dauer.Push(TWSS.getRundeDiskret(TWSS.getBewegungspunktekosten(Z.Peek), False))
                        End If
                    ElseIf TWSS.Einheit.CanAttack Then
                        Z.Push(TWSS.WegsuchenTransporter(True, False))
                        Dauer.Push(TWSS.getRundeDiskret(TWSS.getBewegungspunktekosten(Z.Peek), False))
                    Else
                        Z.Push(TWSS.WegsuchenTransporter(True, True))
                        Dauer.Push(TWSS.getRundeDiskret(TWSS.getBewegungspunktekosten(Z.Peek), False))
                    End If
                Next

                'Fuer jedes Ziel schauen ob es ein nuetzliches Ziel ist.
                Dim BesteZielLandschaft As ObjektLandschaft = Nothing
                Dim MaxDauer As Integer = -1
                Dim Entladungsplaetze As Integer = 0
                'Hier sollte man am besten noch schauen was das beste Feld ist!
                'Ideal waere alle Entladungsfelder durch gehen und schauen ob wir Runden maessig hier am wenigsten Zeit brauchen!
                For I = 0 To Z.Count - 1
                    Dim D As Integer = Dauer(I)
                    Dim P As Point = Z(I)
                    If P.X >= 0 Then
                        If TWSSS(I).Ziel(P.X, P.Y, Schlachtfeld, True, , False) Then
                            Dim TStelle As Integer = TWSSS(I).WegpunkteX.Length - 1
                            'Schauen von welchem Feld aus wir entladen!
                            If TStelle < 0 Then
                                L = Objektverwalter.Spielfeld.Landschaften(P.X, P.Y, Schlachtfeld)
                            Else
                                L = Objektverwalter.Spielfeld.Landschaften(TWSSS(I).WegpunkteX(TStelle), TWSSS(I).WegpunkteY(TStelle), Schlachtfeld)
                            End If
                            If WSS.getBewegungspunktekosten(L.KooX, L.KooY, Schlachtfeld) >= 0 And Transporter.EntladungsUntergrund.Contains(L.getID) And (Not (TWSSS(I).Einheit.KannBesetzen And IsInfiTransporter(Transporter))) Then
                                'Auch ein Ziel!
                                Dim TDauer As Integer = WSS.getRundeDiskret(WSS.getBewegungspunktekosten(L.KooX, L.KooY, Schlachtfeld), False)
                                If TDauer > D Then D = TDauer
                                'Sind wir schneller dort?
                                If D <= MaxDauer Or MaxDauer < 0 Then
                                    'In dieser Runde?
                                    If MaxDauer = 0 Then
                                        Dim EFelder As Integer = GetEntladungsFelder(Transporter, L)
                                        'Koennen wir mehr Truppen entladen?
                                        If EFelder > Entladungsplaetze Then
                                            'Unser neues Ziel!
                                            MaxDauer = D
                                            BesteZielLandschaft = L
                                            Entladungsplaetze = EFelder
                                        End If
                                    Else
                                        'Dann brauchen wir noch etwas!
                                        MaxDauer = D
                                        BesteZielLandschaft = L
                                        Entladungsplaetze = 0
                                    End If
                                End If
                            Else
                                Dim SPunkt As New Point(L.KooX, L.KooY)
                                L = Wegsuchsystem.getFeldRundrum(SPunkt.X, SPunkt.Y, Schlachtfeld, 1, 1, Nothing, Objektverwalter.Spielfeld)
                                Do Until L Is Nothing
                                    If WSS.getBewegungspunktekosten(L.KooX, L.KooY, Schlachtfeld) >= 0 Then
                                        If Transporter.EntladungsUntergrund.Contains(L.getID) Then
                                            'Dies ist ein Feld von dem wir koennen drauf und auch entladen!
                                            Dim TDauer As Integer = WSS.getRundeDiskret(WSS.getBewegungspunktekosten(L.KooX, L.KooY, Schlachtfeld), False)
                                            If TDauer > D Then D = TDauer
                                            'Sind wir schneller dort?
                                            If D <= MaxDauer Or MaxDauer < 0 Then
                                                'In dieser Runde?
                                                If MaxDauer = 0 Then
                                                    Dim EFelder As Integer = GetEntladungsFelder(Transporter, L)
                                                    'Koennen wir mehr Truppen entladen?
                                                    If EFelder > Entladungsplaetze Then
                                                        'Unser neues Ziel!
                                                        MaxDauer = D
                                                        BesteZielLandschaft = L
                                                        Entladungsplaetze = EFelder
                                                    End If
                                                Else
                                                    'Dann brauchen wir noch etwas!
                                                    MaxDauer = D
                                                    BesteZielLandschaft = L
                                                    Entladungsplaetze = 0
                                                End If
                                            End If
                                        End If
                                    End If
                                    L = Wegsuchsystem.getFeldRundrum(SPunkt.X, SPunkt.Y, Schlachtfeld, 1, 1, L, Objektverwalter.Spielfeld)
                                Loop
                            End If
                        End If
                    End If
                Next
                'So Ziel gefunden und los geht es!
                L = BesteZielLandschaft
                If L IsNot Nothing Then
                    WSS.Ziel(L.KooX, L.KooY, Schlachtfeld, True)
                    'Weg zum Ziel berechnen!
                    If WSS.WegpunkteX(0) = L.KooX Then
                        If WSS.WegpunkteY(0) = L.KooY Then
                            'So wir koennen das Ziel erreichen in dieser Runde.
                            Dim ZPunkt As Point = New Point(WSS.WegpunkteX(0), WSS.WegpunkteY(0))
                            For I2 = 0 To TWSSS.Length - 1
                                L = Wegsuchsystem.getFeldRundrum(ZPunkt.X, ZPunkt.Y, Schlachtfeld, 1, 1, Nothing, Objektverwalter.Spielfeld)
                                'Truppen entladungsfelder berechnen
                                Dim ErstesZiel As New Point2(ZPunkt, New Point(-1, -1))
                                Do Until L Is Nothing
                                    If TWSSS(I2).getBewegungspunktekosten(L.KooX, L.KooY, Schlachtfeld) >= 0 Then
                                        If Objektverwalter.Spielfeld.Einheiten(L.KooX, L.KooY, Schlachtfeld) Is Nothing Then
                                            'Hoffentlich entladen wir auf dieses Feld nichts!
                                            For Each P In Ziel
                                                If P.Point2.X = L.KooX Then
                                                    If P.Point2.X = L.KooX Then
                                                        'Naechste Landschaft und erneut pruefen
                                                        L = Wegsuchsystem.getFeldRundrum(ZPunkt.X, ZPunkt.Y, Schlachtfeld, 1, 1, L, Objektverwalter.Spielfeld)
                                                        Continue Do
                                                    End If
                                                End If
                                            Next
                                            'Feld gefunden naechstes Feld
                                            If ErstesZiel.Point2.X < 0 Then
                                                ErstesZiel.Point2 = New Point(L.KooX, L.KooY)
                                            Else
                                                If TWSSS(I2).WegpunkteX.Contains(L.KooX) And TWSSS(I2).WegpunkteY.Contains(L.KooY) Then
                                                    ErstesZiel.Point2 = New Point(L.KooX, L.KooY)
                                                End If
                                            End If
                                        End If
                                    End If
                                    L = Wegsuchsystem.getFeldRundrum(ZPunkt.X, ZPunkt.Y, Schlachtfeld, 1, 1, L, Objektverwalter.Spielfeld)
                                Loop

                                'Nichts gefunden die Einheit kann nicht entladen werden.
                                Ziel.Push(ErstesZiel)
                            Next
                        Else
                            'Wir brauchen noch ein paar Runden
                            'Nur das Ziel zurueck geben
                            Ziel.Push(New Point2(New Point(WSS.WegpunkteX(0), WSS.WegpunkteY(0)), New Point(-1, -1)))
                        End If
                    Else
                        'Nur das Ziel zurueck geben
                        Ziel.Push(New Point2(New Point(WSS.WegpunkteX(0), WSS.WegpunkteY(0)), New Point(-1, -1)))
                    End If
                Else
                    MoveUnitToTransporter(Transporter)
                End If
            Else 'Wir wollen Truppen beladen.
                WSS.BerechnungsStart(Transporter, , True)
                'Alle Truppen sammeln die geladen werden koennen oder sollen
                Dim ZielWSSs As New Stack(Of Wegsuchsystem)
                For Each Unit In Einheiten
                    If ExistUnit(Unit) Then
                        If Transporter.IsLoadable(Unit) = True Then
                            Dim NWSS As New Wegsuchsystem(Unit, , False)
                            Dim Dauer As Integer = CalculateZugDauer(Unit, NWSS.Wegsuchen(True, Unit.KannBesetzen))
                            If Unit.KannBesetzen Then
                                If Dauer > 2 Or Dauer < 0 Then
                                    ZielWSSs.Push(NWSS)
                                End If
                            ElseIf Dauer < 0 Then
                                ZielWSSs.Push(NWSS)
                            End If
                        End If
                    End If
                Next
                'Truppen verladenungsziel bestimmen.
                Dim V As Vector4 = GetMinimaleDauer(ZielWSSs, WSS)
                Ziel.Push(New Point2(New Point(V.X, V.Y), New Point(-1, -1)))
            End If
        Else
            Ziel.Push(New Point2(New Point(-1, -1), New Point(-1, -1)))
        End If
        Dim Ziel2 As New Stack(Of Point2)
        While Ziel.Count > 0
            Dim Z As Point2 = Ziel.Pop
            If Z.Point1 = Z.Point2 Then
                Z.Point2 = New Point(-1, -1)
            End If
            Ziel2.Push(Z)
        End While
        Return Ziel2
    End Function
    Public Function IsInfiTransporter(ByVal T As ObjektEinheit)
        If TypeOf T Is EinheitTTP Then
            Return True
        ElseIf TypeOf T Is EinheitTTL Then
            Return True
        ElseIf TypeOf T Is EinheitTransporthelikopter Then
            Return True
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Berechnet die Dauer die man minimal braucht damit sich die beiden Truppen treffen.
    ''' </summary>
    ''' <param name="ZielWSSs"></param>
    ''' <returns>X=Koo;Y=Koo;Z=Dauer;W=ZielWSSs Index</returns>
    ''' <remarks></remarks>
    Public Function GetMinimaleDauer(ByVal ZielWSSs As Stack(Of Wegsuchsystem), ByVal WSS As Wegsuchsystem) As Vector4
        Dim V As New Vector4(-1, -1, -1, -1)
        For X = 0 To Objektverwalter.Spielfeld.Breite - 1
            For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                Dim Dauer As Integer = WSS.getRundeDiskret(WSS.getBewegungspunktekosten(X, Y, Schlachtfeld), False)
                If Dauer >= 0 Then
                    If Dauer < V.Z Or V.Z < 0 Then
                        Dim Dauer2 As Integer = Dauer
                        Dim ZIndex As Integer = -1
                        For I = 0 To ZielWSSs.Count - 1
                            Dim Dauer3 As Integer = ZielWSSs(I).getRundeDiskret(ZielWSSs(I).getBewegungspunktekosten(X, Y, Schlachtfeld), False)
                            If ZIndex < 0 Then
                                If Dauer3 >= 0 Then
                                    If Dauer3 > Dauer Then
                                        Dauer2 = Dauer3
                                        ZIndex = I
                                    Else
                                        ZIndex = I
                                    End If
                                End If
                            Else
                                If Dauer3 >= 0 Then
                                    If Dauer3 >= Dauer Then
                                        If Dauer3 < Dauer2 Then
                                            ZIndex = I
                                            Dauer2 = Dauer3
                                        End If
                                    End If
                                End If
                            End If
                        Next
                        If ZIndex >= 0 Then
                            V = New Vector4(X, Y, Dauer2, ZIndex)
                        End If
                    End If
                End If
            Next
        Next
        Return V
    End Function
    ''' <summary>
    ''' Ueberprueft ob mindestens ein P.Point2 ein Feld ist!
    ''' </summary>
    ''' <param name="P"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function ContainsZiel(ByVal P As Stack(Of Point2)) As Boolean
        For Each P2 In P
            If P2.Point2.X >= 0 Then
                If P2.Point2.Y >= 0 Then
                    Return True
                End If
            End If
        Next
        Return False
    End Function
    ''' <summary>
    ''' Wie viele Felder koennen mit Truppen beladen werden?
    ''' </summary>
    ''' <param name="Transporter"></param>
    ''' <param name="Feld"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetEntladungsFelder(ByVal Transporter As ObjektEinheit, ByVal Feld As ObjektLandschaft) As Integer
        Dim EFelder As Integer = 0
        Dim EntladeneTruppen As New Stack(Of Integer)
        Dim L As ObjektLandschaft = Wegsuchsystem.getFeldRundrum(Feld.KooX, Feld.KooY, Schlachtfeld, 1, 1, Nothing, Objektverwalter.Spielfeld)
        Do Until L Is Nothing
            If Objektverwalter.Spielfeld.Einheiten(L.KooX, L.KooY, Schlachtfeld) Is Nothing Then
                'Leeres Feld
                For I = 0 To Transporter.Ladung.Length - 1
                    'Diese Einheit wurde noch nicht entladen
                    If Not EntladeneTruppen.Contains(I) Then
                        Dim E As ObjektEinheit = Transporter.Ladung(I)
                        If E IsNot Nothing Then
                            'Die Einheit kann darueber laufen.
                            If E.CanMoveOverTile(L.KooX, L.KooY, Schlachtfeld) Then
                                'ein weiteres Entladungsfeld.
                                EFelder += 1
                                EntladeneTruppen.Push(I)
                            End If
                        End If
                    End If
                Next
            End If
            L = Wegsuchsystem.getFeldRundrum(Feld.KooX, Feld.KooY, Schlachtfeld, 1, 1, L, Objektverwalter.Spielfeld)
        Loop
        Return EFelder
    End Function

    ''' <summary>
    ''' Verlaedt die Truppen in Transporter
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub EinheitenVerladen()
        While MomentaneEinheit < Einheiten.Length
            Dim Einheit As ObjektEinheit = Einheiten(MomentaneEinheit)
            If ExistUnit(Einheit) = True Then
                If Einheiten(MomentaneEinheit).IsUsingUnit(MinimalerTreibstoff, MinimaleMunition, MinimaleKP) = True Then
                    If Einheit.Ladung.Length = 0 Then
                        'Es ist auch keine Transport Einheit
                        MoveUnitToTransporter(Einheit)
                    End If
                End If
            End If
            MomentaneEinheit += 1
        End While
    End Sub
    Protected Sub MoveUnitToTransporter(ByVal Einheit As ObjektEinheit)
        Dim AlterModus As KIModiIntern = KIModusIntern
        KIModusIntern = KIModiIntern.TransporterVerladen
        Dim WSS As New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, -1)
        Dim Ziel As Vector3 = GetTransporter(Einheit, WSS)
        'Wir haben einen Transporter gefunden!
        If Not Einheit.HatsichBewegt Then
            If Ziel.X >= 0 Then
                If Ziel.Z >= 0 Then
                    'Wir koennen ihn erreichen!
                    If Ziel.Z = 0 Then
                        'Sogar ihn dieser Runde!
                        Einheitauswaehlen(Einheit, New Point(Ziel.X, Ziel.Y), KIModiExtern.Fracht, Nothing, WSS, 4)
                        EinheitGezogenVonVorneStarten()
                        Exit Sub
                    Else
                        Einheitauswaehlen(Einheit, New Point(Ziel.X, Ziel.Y), KIModiExtern.Warten, Nothing, WSS, 4)
                        EinheitGezogenVonVorneStarten()
                        Exit Sub
                    End If
                Else
                    'Leider ist er noch zu weit weg!
                    Einheitauswaehlen(Einheit, New Point(Ziel.X, Ziel.Y), KIModiExtern.Warten, Nothing, WSS, 4)
                    EinheitGezogenVonVorneStarten()
                    Exit Sub
                End If
            ElseIf Ziel.Z < 0 Or Ziel.Z > 0 Then 'Der Transporter kommt noch vorbei und dann sind wir eh weg!
                'schauen wir mal ob unter uns ein Gebaeude ist
                Dim Gebaeude As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(Einheit.X, Einheit.Y, Schlachtfeld).Gebaeude
                If Not Gebaeude Is Nothing Then
                    If Gebaeude.GetBaulisteThisPlayer.Length > 0 And Spieler.Team = Objektverwalter.Spielfeld.Spieler(Gebaeude.Spieler).Team Then
                        Dim Ziele As Point() = GetFreeFelder(Einheit, WSS, True)
                        If Ziele.Length > 0 Then
                            Einheitauswaehlen(Einheit, Ziele(Zufallszahl(0, Ziele.Length - 1)), KIModiExtern.Warten, Nothing, WSS, 4)
                            EinheitGezogenVonVorneStarten()
                            Exit Sub
                        End If
                    End If
                End If
            End If
        End If
        KIModusIntern = AlterModus
    End Sub
    ''' <summary>
    ''' Findet den naehesten Transporter zu dem wir hin ziehen sollten!
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS">Das Wegsuchsystem! Wichtig: komplett ausgebreitet!</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetTransporter(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Vector3
        Dim Ziel As New Vector3(-1, -1, -1)
        Dim TransporterWSS As New Stack(Of Wegsuchsystem)
        'so jetzt haben wir alle Transporter!
        For Each Transporter In Einheiten
            'Ist es ein Transporter und koennen wir ihn benutzen?
            If Not Transporter.IsLowPowerUnit(MinimalerTreibstoff, MinimaleMunition, MinimaleKP) Then
                If Transporter.Ladung.Length > 0 Then
                    'Kann er uns Transportieren?
                    If Transporter.IsLoadable(Einheit) Then
                        If Transporter.HasLadung Then
                            'Er hat bereits Ladung
                            If WSS.getRundeDiskret(WSS.getBewegungspunktekosten(Transporter.X, Transporter.Y, Transporter.GetMap), False) = 0 Or Transporter.HatsichBewegt Then
                                'Nur wenn wir ihn jetzt erreichen koennen nehmen wir ihn als Ziel.
                                'Ansonsten ist er bereits weg!
                                TransporterWSS.Push(New Wegsuchsystem(Transporter, , True))
                            End If
                        Else
                            'Der Transporter sucht sowieso noch Ladung also her damit!
                            TransporterWSS.Push(New Wegsuchsystem(Transporter, , True))
                        End If
                    End If
                End If
            End If
        Next
        'So jetzt haben wir alle Zieltransporter! Dann suchen wir die kuerzesten Weg zu den beiden!
        If TransporterWSS.Count > 0 Then
            Dim V As Vector4 = GetMinimaleDauer(TransporterWSS, WSS)

            'Ziel suchen!
            If V.W >= 0 Then
                WSS.Ziel(TransporterWSS(V.W).Einheit.X, TransporterWSS(V.W).Einheit.Y, Schlachtfeld, True, , False)
                If WSS.WegpunkteX.Length > 0 Then
                    If WSS.getRundeDiskret(WSS.getBewegungspunktekosten(WSS.WegpunkteX(0), WSS.WegpunkteY(0), Schlachtfeld), False) = 0 Then
                        'Wir erreichen ihn diese Runde!
                        If TransporterWSS(V.W).Einheit.X = WSS.WegpunkteX(0) And TransporterWSS(V.W).Einheit.Y = WSS.WegpunkteY(0) Then
                            Ziel = New Vector3(WSS.WegpunkteX(0), WSS.WegpunkteY(0), V.Z)
                        Else
                            If TransporterWSS(V.W).Einheit.HatsichBewegt Then
                                Ziel = New Vector3(WSS.WegpunkteX(0), WSS.WegpunkteY(0), -1)
                            Else
                                Ziel.Z = V.Z
                            End If
                        End If
                    Else
                        'So jetzt sollten wir natuerlich nicht auf das Feld treten auf dem der Transporter uns abholen will!
                        If V.X = TransporterWSS(V.W).Einheit.X And V.Y = TransporterWSS(V.W).Einheit.Y Then
                            'Der Transporter ist bereits da dann nichts wie rein!
                            Ziel = New Vector3(V.X, V.Y, -1)
                        Else 'Wir gehen ein Feld vorher hin!
                            'ein neben Feld
                            If WSS.Ziel(V.X, V.Y, False) Then
                                Ziel = New Vector3(WSS.WegpunkteX(0), WSS.WegpunkteY(0), -1)
                            End If
                        End If
                    End If
                ElseIf V.Z >= 0 Then
                    Ziel.Z = V.Z
                    If V.Z > 0 Or TransporterWSS(V.W).Einheit.HatsichBewegt Then
                        If TransporterWSS(V.W).Einheit.HatsichBewegt Then
                            'Laufen wir mal zu ihm hin!
                            If WSS.Ziel(TransporterWSS(V.W).Einheit.X, TransporterWSS(V.W).Einheit.Y, Schlachtfeld, False, , False) Then

                                Ziel = New Vector3(WSS.WegpunkteX(0), WSS.WegpunkteY(0), -1)
                            End If
                        Else
                            'So in dieser Runde treffen wir uns nicht
                            If V.X = TransporterWSS(V.W).Einheit.X And V.Y = TransporterWSS(V.W).Einheit.Y Then
                                'Der Transporter ist bereits da dann nichts wie rein!
                                Ziel = New Vector3(V.X, V.Y, V.Z)
                            Else 'Wir gehen ein Feld vorher hin!
                                'ein neben Feld
                                If WSS.Ziel(V.X, V.Y, Schlachtfeld, False, , False) Then

                                    Ziel = New Vector3(WSS.WegpunkteX(0), WSS.WegpunkteY(0), -1)
                                End If
                            End If
                        End If
                    End If
                End If
            End If
        End If
        Return Ziel
    End Function
    ''' <summary>
    ''' Gibt alle Transporter zurueck, die in dieser Runde erreicht werden koennen.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="WSS"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetTransporterDieseRunde(ByVal Einheit As ObjektEinheit, ByRef WSS As Wegsuchsystem) As Point()
        Dim Felder As New Stack(Of Point)
        For Each Transporter In Einheiten
            If Transporter.Ladung.Length > 0 Then
                If Transporter.IsLoadable(Einheit) Then
                    If Not Transporter.IsLowPowerUnit(MinimalerTreibstoff, MinimaleMunition, MinimaleKP) Then
                        If WSS.getRundeDiskret(WSS.GetBewegungspunktekostenReal(Transporter.X, Transporter.Y, Transporter.GetMap), False) = 0 Then
                            'Wir koennen ihn in dieser Runde erreichen!
                            Felder.Push(New Point(Transporter.X, Transporter.Y))
                        End If
                    End If
                End If
            End If
        Next
        Return Felder.ToArray
    End Function
    ''' <summary>
    ''' Sucht die naeheste Besetzung und schaut dann ob wir einen Transporter nehmen oder nicht. Wenn wir ziehen geben wir True zurueck!
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function InfantrieMoveToTransporterOrBesetzung(ByVal Einheit As ObjektEinheit) As Boolean
        Dim AltModus As KIModiIntern = KIModusIntern
        'Wir simulieren, wir wuerden Truppen verladen
        KIModusIntern = KIModiIntern.TransporterVerladen
        Dim WSS As New Wegsuchsystem(Einheit, , True)
        Dim Zielpunkt As Point = GetNaehesteBesetzung(Einheit, WSS)
        'Koennen wir eine Besetzung ueber Land erreichen?
        If Zielpunkt.X >= 0 Then
            Dim Dauer As Integer = WSS.getRundeDiskret(WSS.getBewegungspunktekosten(Zielpunkt), False)
            If Dauer >= 2 Then
                Dim Transporter() As Point = GetAllTTPsAndTHelis(GetTransporterDieseRunde(Einheit, WSS))
                If Transporter.Length > 0 Then
                    'Hier sollten wir den besten Transporter aussuchen!
                    Dim BesterTransporter As New Point(-1, -1)
                    Dim MinDauer As Integer = -1
                    For Each T In Transporter
                        Dim Trans As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(T.X, T.Y, Schlachtfeld)
                        Dim TWSS As New Wegsuchsystem(Trans, , True)
                        If TWSS.Ziel(Zielpunkt.X, Zielpunkt.Y, False) Then
                            Dim D2 As Integer = TWSS.getRundeDiskret(TWSS.getBewegungspunktekosten(Zielpunkt.X, Zielpunkt.Y, Schlachtfeld), False)
                            'Wir kommen zum Ziel
                            If D2 < MinDauer Or MinDauer < 0 Then
                                BesterTransporter = T
                                MinDauer = D2
                            End If
                        End If
                    Next
                    If BesterTransporter.X >= 0 Then
                        'Der Transporter ist der beste!
                        Einheitauswaehlen(Einheit, BesterTransporter, KIModiExtern.Fracht, Nothing, WSS, 4)
                        EinheitGezogenVonVorneStarten()
                        Return True
                    Else
                        'Wir laufen schon mal los kein Transporter ist ein nuetzlicher! Seltsam!
                        Einheitauswaehlen(Einheit, Zielpunkt, KIModiExtern.Warten, Nothing, WSS)
                        EinheitGezogenVonVorneStarten()
                        Return True
                    End If
                Else
                    'Wir laufen schon mal los!
                    Einheitauswaehlen(Einheit, Zielpunkt, KIModiExtern.Warten, Nothing, WSS)
                    EinheitGezogenVonVorneStarten()
                    Return True
                End If
            Else 'wir koennen so hin laufen!
                Einheitauswaehlen(Einheit, Zielpunkt, KIModiExtern.Warten, Nothing, WSS)
                EinheitGezogenVonVorneStarten()
                Return True
            End If
        Else
            KIModusIntern = AltModus
            'Nicht gut! Also per Land geht da rein gar nichts!
            Return False
        End If
        KIModusIntern = AltModus
    End Function
    ''' <summary>
    ''' Gibt aus einem Array von Zieltransportern, die zurueck, die TTPs oder T-Helis oder TTLs sind.
    ''' </summary>
    ''' <param name="Transporter"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function GetAllTTPsAndTHelis(ByVal Transporter() As Point) As Point()
        Dim T As New Stack(Of Point)
        For Each E In Transporter
            If Objektverwalter.Spielfeld.Einheiten(E.X, E.Y, Schlachtfeld).EinheitenID = "TTP" Or Objektverwalter.Spielfeld.Einheiten(E.X, E.Y, Schlachtfeld).EinheitenID = "T-HELI" Or Objektverwalter.Spielfeld.Einheiten(E.X, E.Y, Schlachtfeld).EinheitenID = "TTL" Then
                T.Push(E)
            End If
        Next
        Return T.ToArray
    End Function
#End Region
#Region "Einheiten System"
    Private Class BesetzungsGebaeude
        Public X As Integer
        Public Y As Integer
        Public Units As New List(Of Integer)
        Public ListenStelle As Integer
        Public Sub New(ByVal X As Integer, ByVal Y As Integer, ByVal Unit As Integer, ByVal Listenstelle As Integer)
            Units.Add(Unit)
            Me.X = X
            Me.Y = Y
            Me.ListenStelle = Listenstelle
        End Sub
    End Class
    ''' <summary>
    ''' Besetzt Gebaeude intelligenter!
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub GebaeudeBesetzen()
        Dim Besetzungen As New List(Of BesetzungsGebaeude)
        While MomentaneEinheit < Einheiten.Length
            If ExistUnit(Einheiten(MomentaneEinheit)) = True Then
                Dim Einheit As ObjektEinheit = Einheiten(MomentaneEinheit)
                If Einheit.KannBesetzen = True Then
                    If Einheit.HatsichBewegt = False Then
                        Dim WSS As New Wegsuchsystem(Einheit, Einheit.X, Einheit.Y, Einheit.GetMap, Einheit.GetMovementRange, , Wegsuchsystem.SuchartenEinheiten.EigeneEinheitenIgnorieren)
                        If Einheit.Besetzen = True Then
                            'Diese Einheit besetzt gerade ein Gebaeude da macht sie damit gleich weiter
                            Einheitauswaehlen(Einheit, New Point(Einheit.X, Einheit.Y), KIModiExtern.Besetzen, Nothing, WSS, 4)
                        Else
                            Dim Mov As Integer = Einheit.GetMovementRange
                            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                                    Dim Bew = WSS.getBewegungspunktekosten(X, Y, Einheit.GetMap)
                                    If Bew >= 0 And Bew <= Mov Then
                                        If Objektverwalter.Spielfeld.Einheiten(X, Y, Einheit.GetMap) Is Nothing Or (Einheit.X = X And Einheit.Y = Y) Then
                                            Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X, Y, Einheit.GetMap).Gebaeude
                                            If G IsNot Nothing Then
                                                If G.IsBesetzung(Einheit) Then
                                                    If G.GetSpieler.Team <> Spieler.Team Then
                                                        If Besetzungen.Count > 0 Then
                                                            For I = 0 To Besetzungen.Count - 1
                                                                If Besetzungen(I).X = X Then
                                                                    If Besetzungen(I).Y = Y Then
                                                                        Besetzungen(I).Units.Add(MomentaneEinheit)
                                                                        Exit For
                                                                    End If
                                                                End If
                                                                If I = Besetzungen.Count - 1 Then
                                                                    Besetzungen.Add(New BesetzungsGebaeude(X, Y, MomentaneEinheit, Besetzungen.Count))
                                                                End If
                                                            Next
                                                        Else
                                                            Besetzungen.Add(New BesetzungsGebaeude(X, Y, MomentaneEinheit, 0))
                                                        End If
                                                    End If
                                                End If
                                            End If
                                        End If
                                    End If
                                Next
                            Next
                        End If
                    End If
                End If
            End If
            MomentaneEinheit += 1
        End While
        'So jetzt wissen wir welche Einheit welche Gebaeude besetzen kann.
        MomentaneEinheit = 0
        Besetzungen.Sort(AddressOf CompareBesetzungen)
        For I = 0 To Besetzungen.Count - 1
            Besetzungen(I).ListenStelle = I
        Next
        Dim NichtGezogen As Boolean = False
        While MomentaneEinheit < Einheiten.Length
            If ExistUnit(Einheiten(MomentaneEinheit)) = True Then
                Dim Einheit As ObjektEinheit = Einheiten(MomentaneEinheit)
                If Einheit.KannBesetzen = True Then
                    If Einheit.HatsichBewegt = False Then
                        Dim WSS As Wegsuchsystem = CreateWSS(Einheit)
                        Dim Gebaeude As New List(Of BesetzungsGebaeude)
                        For I = 0 To Besetzungen.Count - 1
                            If Besetzungen(I).Units.Contains(MomentaneEinheit) Then
                                Gebaeude.Add(Besetzungen(I))
                            End If
                        Next
                        If Gebaeude.Count > 0 Then
                            If Gebaeude(0).Units.Count = 1 Then
                                Capture(Einheit, Gebaeude, WSS, Besetzungen)
                            ElseIf (Gebaeude(0).Units.Count > 1 And Not Contains1Units(Besetzungen)) Then
                                Capture(Einheit, Gebaeude, WSS, Besetzungen)
                            ElseIf Gebaeude.Count = 1 Then
                                Capture(Einheit, Gebaeude, WSS, Besetzungen)
                            Else
                                Dim Found As Boolean = False
                                For I = 0 To Gebaeude.Count - 1
                                    For i2 = 0 To Gebaeude.Count - 1
                                        If i2 <> I Then
                                            For i3 = 0 To Gebaeude(I).Units.Count - 1
                                                If Gebaeude(I).Units(i3) <> MomentaneEinheit Then
                                                    For i4 = 0 To Gebaeude(i2).Units.Count - 1
                                                        If Gebaeude(i2).Units(i4) <> MomentaneEinheit Then
                                                            If Gebaeude(I).Units(i3) = Gebaeude(i2).Units(i4) Then
                                                                Dim G As New List(Of BesetzungsGebaeude)
                                                                G.Add(Gebaeude(i3))
                                                                Capture(Einheit, G, WSS, Besetzungen)
                                                                Found = True
                                                                Exit For
                                                            End If
                                                        End If
                                                    Next

                                                End If
                                                If Found Then Exit For
                                            Next
                                        End If
                                        If Found Then Exit For
                                    Next
                                    If Found Then Exit For
                                Next
                                NichtGezogen = Not Found
                            End If
                        End If
                    End If
                End If
            End If
            MomentaneEinheit += 1
            If NichtGezogen Then
                If MomentaneEinheit >= Einheiten.Length Then
                    NichtGezogen = False
                    MomentaneEinheit = 0
                End If
            End If
        End While
        MomentaneEinheit = 0
    End Sub
    Private Shared Function CompareBesetzungen(ByVal x As BesetzungsGebaeude, ByVal y As BesetzungsGebaeude) As Integer

        If x Is Nothing Then
            If y Is Nothing Then
                ' If x is Nothing and y is Nothing, they're
                ' equal. 
                Return 0
            Else
                ' If x is Nothing and y is not Nothing, y
                ' is greater. 
                Return 1
            End If
        Else
            ' If x is not Nothing...
            '
            If y Is Nothing Then
                ' ...and y is Nothing, x is greater.
                Return -1
            Else
                ' ...and y is not Nothing, compare the 
                ' lengths of the two strings.
                '
                If x.Units.Count < y.Units.Count Then
                    Return -1
                ElseIf x.Units.Count > y.Units.Count Then
                    Return 1
                Else
                    Dim G1 As Integer = Objektverwalter.Spielfeld.Landschaften(x.X, x.Y, Schlachtfeld).Gebaeude.GetBauliste.Length
                    Dim G2 As Integer = Objektverwalter.Spielfeld.Landschaften(y.X, y.Y, Schlachtfeld).Gebaeude.GetBauliste.Length
                    If G1 > G2 Then
                        Return -1
                    ElseIf G1 < G2 Then
                        Return 1
                    Else
                        Return 0
                    End If
                End If
            End If
        End If

    End Function
    Private Shared Function Contains1Units(ByVal Besetzungen As List(Of BesetzungsGebaeude)) As Boolean
        For I = 0 To Besetzungen.Count - 1
            If Besetzungen(I).Units.Count = 1 Then
                Return True
            End If
        Next
        Return False
    End Function
    Private Sub Capture(ByVal Einheit As ObjektEinheit, ByVal Gebaeude As List(Of BesetzungsGebaeude), ByVal WSS As Wegsuchsystem, ByRef Besetzungen As List(Of BesetzungsGebaeude))
        Gebaeude.Sort(AddressOf CompareBesetzungen)

        WSS.Ziel(Gebaeude(0).X, Gebaeude(0).Y, True)
        Dim Bes As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(Gebaeude(0).X, Gebaeude(0).Y, Schlachtfeld).Gebaeude
        If Bes.Angriff = ObjektGebaeude.Angriffe.Silo Then
            Dim Ziel2 As Point = GetBestenEinschlagsOrt(Bes.Reichweite, Bes.Schaden)
            Einheitauswaehlen(Einheit, New Point(Gebaeude(0).X, Gebaeude(0).Y), KIModiExtern.SiloZuenden, New EinheitAmphibienpanzer(0, Ziel2.X, Ziel2.Y), WSS, 4)
        Else
            Einheitauswaehlen(Einheit, New Point(Gebaeude(0).X, Gebaeude(0).Y), KIModiExtern.Besetzen, Nothing, WSS, 4)
        End If
        Besetzungen.RemoveAt(Gebaeude(0).ListenStelle)
        Dim I As Integer = 0
        While I < Gebaeude.Count
            For I2 = 0 To Gebaeude(I).Units.Count - 1
                If Gebaeude(I).Units(I2) = MomentaneEinheit Then
                    If Gebaeude(I).Units.Count = 1 Then
                        Gebaeude.RemoveAt(I)
                        I -= 1
                    Else
                        Gebaeude(I).Units.RemoveAt(I2)
                    End If
                    Exit For
                End If
            Next
            I += 1
        End While
        For I = 0 To Besetzungen.Count - 1
            Besetzungen(I).ListenStelle = I
        Next
    End Sub
#End Region
#Region "Einheit ziehen und Befehle"
    ''' <summary>
    ''' Fuehrt den momentanen Befehl fuer die Einheit oder das Gebaeude aus
    ''' </summary>
    ''' <param name="Wait">If False Everything is done as fast as possible No Visual Style</param>
    ''' <remarks></remarks>
    Private Sub DoBefehl(ByVal Wait As Boolean)
        If Objektverwalter.Spielfeld.AktuelleEinheit IsNot Nothing Then

            Select Case KIModusEinheitenBefehl
                'Hier stehen EinheitenBefehle. Zwei wurden ausgeklammert
                Case KIModiExtern.Warten
                    Objektverwalter.Warten()
                Case KIModiExtern.Angriff
                    Dim Entfernung As Integer = AktuelleEinheit.GetDistance(Opfer)
                    If Entfernung >= AktuelleEinheit.MinimaleReichweite And Entfernung <= AktuelleEinheit.MaximaleReichweite Or Entfernung = 1 And AktuelleEinheit.Waffe1 <> "Keine" Then
                        If TypeOf Me Is KIPassivNetzwerk Then
                            Objektverwalter.Angriff(AktuelleEinheit, Opfer.X, Opfer.Y, AngreiferSchaden, VerteidigerSchaden)
                        Else
                            Objektverwalter.Angriff(AktuelleEinheit, Opfer.X, Opfer.Y)
                        End If
                        If Not Wait Then
                            'We need to Finish this fast!!!
                            Objektverwalter.Spielfeld.Angriff.AngriffEnde()
                            ObjektScript.Pruefen(ObjektScript.Pruefstadien.RundenMitte)
                            Objektverwalter.Spielfeld.Angriff = Nothing
                            Objektverwalter.Spielfeld.Regeln.CheckSieg()
                        End If
                    Else
                        Objektverwalter.Warten()
                    End If
                Case KIModiExtern.Besetzen
                    Objektverwalter.Besetzen()
                Case KIModiExtern.Einen
                    Objektverwalter.Einen()
                Case KIModiExtern.Ration
                    Objektverwalter.Ration(False, 4, Objektverwalter.Spielfeld.MomentaneSchlacht)
                Case KIModiExtern.Fracht
                    Objektverwalter.Fracht()
                Case KIModiExtern.Reparieren
                    Objektverwalter.Reparieren(Opfer.X, Opfer.Y)
                Case KIModiExtern.Tarnen
                    Objektverwalter.Tarnen()
                Case KIModiExtern.Auftauchen
                    Objektverwalter.Auftauchen()
                Case KIModiExtern.Explosion
                    Objektverwalter.Explosion()
                Case KIModiExtern.SiloZuenden
                    Objektverwalter.SiloZuenden(Opfer.X, Opfer.Y)
                Case KIModiExtern.Entladen
                    If Objektverwalter.Spielfeld.Laufen Is Nothing Then
                        If AktuelleZiel.X = AktuelleEinheit.X And AktuelleZiel.Y = AktuelleEinheit.Y Then
                            Objektverwalter.Entladen(Opfer.X, Opfer.Y, AngreiferSchaden)
                        Else
                            Objektverwalter.Warten()
                        End If
                    ElseIf AktuelleZiel.X = Objektverwalter.Spielfeld.Laufen.Position.X And AktuelleZiel.Y = Objektverwalter.Spielfeld.Laufen.Position.Y Then
                        Objektverwalter.Entladen(Opfer.X, Opfer.Y, AngreiferSchaden)
                    Else
                        Objektverwalter.Warten()
                    End If
                Case KIModiExtern.GebaeudeBauen
                    Dim ID As String = ObjektLadeklasse.GetGebaeudeStringID(AngreiferSchaden)
                    Dim M As ObjektSpielMenue = Objektverwalter.Menue
                    If ID = "MAUER" Then
                        M.Spielmodus = ObjektSpielMenue.Spielmodi.MauerBauen
                        Objektverwalter.MauerBrueckeBauen(Opfer.X, Opfer.Y)
                    ElseIf ID = "BRUECKE" Then
                        M.Spielmodus = ObjektSpielMenue.Spielmodi.BrueckeBauen
                        Objektverwalter.MauerBrueckeBauen(Opfer.X, Opfer.Y)
                    Else
                        Objektverwalter.GebaeudeBauen(Opfer.X, Opfer.Y, ID)
                    End If
                Case KIModiExtern.FlugzeugtraegerBau
                    If Spieler.VeraenderteWerte.KeinBau = False Then
                        AnzahldesBauens += 1
                        Objektverwalter.EinheitBauenFlugzeugtraeger(New String() {Opfer.EinheitenID, Opfer.Kosten * Spieler.Teurungsrate(Opfer, BauGebaeude.Rechteck.X, BauGebaeude.Rechteck.Y)}, BauGebaeude.Rechteck.X, BauGebaeude.Rechteck.Y, True, True)
                        Objektverwalter.ZuFeldgehen(Opfer.X, Opfer.Y)
                    End If
                Case KIModiExtern.TemporaereBasisbauen
                    Objektverwalter.BuildTempBase()
                Case KIModiExtern.Leuchtrakete
                    Objektverwalter.LechtraketeAbfeuern(Opfer.X, Opfer.Y)
                Case KIModiExtern.CreateKOEinheit
                    Objektverwalter.CreateKOEinheit()
                    'ab hier stehen Gebaeudebefehle.
                Case KIModiExtern.EinheitBauen
                    If Spieler.VeraenderteWerte.KeinBau = False Then
                        AnzahldesBauens += 1
                        Objektverwalter.EinheitBauen(New String() {Opfer.EinheitenID, Opfer.Kosten * Spieler.Teurungsrate(Opfer, BauGebaeude.Rechteck.X, BauGebaeude.Rechteck.Y)}, BauGebaeude.Rechteck.X, BauGebaeude.Rechteck.Y, True, True)
                        Objektverwalter.ZuFeldgehen(Opfer.X, Opfer.Y)
                    End If

                Case KIModiExtern.EinheitSchicken
                    Objektverwalter.Schicken()
                Case KIModiExtern.Schuss
                    BauGebaeude.Feuer(Opfer.X, Opfer.Y)
                Case KIModiExtern.OmegaRaketeStarten
                    Dim Omega As GebaeudeOmega_Rakete = BauGebaeude
                    Omega.RaketeStarten(Opfer.X, Opfer.Y)
                Case KIModiExtern.FabrikBauen
                    Dim Fabrik As GebaeudeFabrik = BauGebaeude
                    Fabrik.Bauen(Opfer.Einheitenname, Opfer.X, Opfer.Y, True)
                    If Opfer.X = Fabrik.Rechteck.X Then
                        Fabrik.Variablen(0).Wert -= 2
                    ElseIf Opfer.X < Fabrik.Rechteck.X Then
                        Fabrik.Variablen(0).Wert -= 1
                    Else
                        Fabrik.Variablen(0).Wert -= 4
                    End If
                    Objektverwalter.ZuFeldgehen(Opfer.X, Opfer.Y)
                Case KIModiExtern.OmegaUpgradeKaufen
                    Dim Omega As GebaeudeOmega_Rakete = BauGebaeude
                    Omega.ErweiterungKaufen(Omega.Variablen(Opfer.X).Name)
                    Objektverwalter.ZuFeldgehen(Opfer.X, Opfer.Y)

            End Select
        Else
            Select Case KIModusEinheitenBefehl
                Case KIModiExtern.EinheitBauen
                    If Spieler.VeraenderteWerte.KeinBau = False Then
                        AnzahldesBauens += 1
                        Objektverwalter.EinheitBauen(New String() {Opfer.EinheitenID, Opfer.Kosten * Spieler.Teurungsrate(Opfer, BauGebaeude.Rechteck.X, BauGebaeude.Rechteck.Y)}, BauGebaeude.Rechteck.X, BauGebaeude.Rechteck.Y, True, True)
                        Objektverwalter.ZuFeldgehen(Opfer.X, Opfer.Y)
                    End If
                Case KIModiExtern.Schuss
                    BauGebaeude.Feuer(Opfer.X, Opfer.Y)
                Case KIModiExtern.OmegaRaketeStarten
                    Dim Omega As GebaeudeOmega_Rakete = BauGebaeude
                    Omega.RaketeStarten(Opfer.X, Opfer.Y)
                Case KIModiExtern.FabrikBauen
                    Dim Fabrik As GebaeudeFabrik = BauGebaeude
                    Fabrik.Bauen(Opfer.Einheitenname, Opfer.X, Opfer.Y, True)
                    If Opfer.X = Fabrik.Rechteck.X Then
                        Fabrik.Variablen(0).Wert -= 2
                    ElseIf Opfer.X < Fabrik.Rechteck.X Then
                        Fabrik.Variablen(0).Wert -= 1
                    Else
                        Fabrik.Variablen(0).Wert -= 4
                    End If
                    Objektverwalter.ZuFeldgehen(Opfer.X, Opfer.Y)
                Case KIModiExtern.OmegaUpgradeKaufen
                    Dim Omega As GebaeudeOmega_Rakete = BauGebaeude
                    Omega.ErweiterungKaufen(Omega.Variablen(Opfer.X).Name)
                    Objektverwalter.ZuFeldgehen(Opfer.X, Opfer.Y)
                Case Else
                    'Do nothing
            End Select
        End If
        KIModusEinheitenBefehl = KIModiExtern.Keiner
        If Wait Then KIWarten(2)
        If Not KIModusEinheitenBefehl = KIModiExtern.EinheitBauen And Not KIModusEinheitenBefehl = KIModiExtern.FabrikBauen Then
            MomentaneEinheit -= 1
        End If
        If MomentaneEinheit < 0 Then MomentaneEinheit = 0

        ObjektMaus.Visible = False
        Objektverwalter.Spielfeld.EingabenErlauben = False
        CreateSicht(Sichtfeld, Spieler)
    End Sub
    Protected Sub EinheitAbwaehlen()
        Objektverwalter.Einheitabwaehlen(True)
        AktuelleEinheit = Nothing
        AktuelleZiel = New Point
        Opfer = Nothing
        KIModusEinheitenBefehl = KIModiExtern.Keiner
    End Sub
    ''' <summary>
    ''' Fuehrt einen Befehl fuer eine Einheit aus
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="Ziel"></param>
    ''' <param name="Aktion"></param>
    ''' <param name="Gegner"></param>
    ''' <param name="Warten"></param>
    ''' <remarks></remarks>
    Protected Sub Einheitauswaehlen(ByVal Einheit As ObjektEinheit, ByVal Ziel As Point, ByVal Aktion As KIModiExtern, ByVal Gegner As ObjektEinheit, ByRef WSS As Wegsuchsystem, Optional ByVal Warten As Integer = 2, Optional ByVal Wait As Boolean = True)
        If Not Einheit Is Nothing Then
            Objektverwalter.ZuFeldgehen(Einheit.X, Einheit.Y)
            Dim Spielmenue As ObjektSpielMenue = Objektverwalter.Menue
            AktuelleEinheit = Einheit
            AktuelleZiel = Ziel
            KIModusEinheitenBefehl = Aktion
            Opfer = Gegner
            If Ziel.X <> Einheit.X Or Ziel.Y <> Einheit.Y Then
                If WSS Is Nothing Then
                    WSS = New Wegsuchsystem(Einheit)
                End If

                Select Case Aktion
                    Case KIModiExtern.Fracht, KIModiExtern.Einen
                        WSS.Ziel(Ziel.X, Ziel.Y, True, False)
                    Case Else
                        WSS.Ziel(Ziel.X, Ziel.Y, True, True)
                End Select

                If WSS.WegpunkteX.Length = 0 Then
                    Ziel = Einheit.GetLocation
                Else
                    Ziel = New Point(WSS.WegpunkteX(0), WSS.WegpunkteY(0))
                End If

            End If

            Objektverwalter.Einheitauswaehlen(AktuelleEinheit.X, AktuelleEinheit.Y, WSS)
            If Not WSS Is Nothing Then
                If WSS.WegpunkteX.Length > 1 Then
                    Spielmenue.EinheitBewegungsBefehl(Ziel.X, Ziel.Y)
                End If
            End If
            AufBefehlEndeWarten(Aktion, Warten, Wait)
        End If
    End Sub
    ''' <summary>
    ''' Wir haben eine Einheit ausgewaehlt und wollen mit ihr noch einen weiteren Befehl ausueben.
    ''' </summary>
    ''' <param name="Ziel"></param>
    ''' <param name="Gegner"></param>
    ''' <param name="Befehl"></param>
    ''' <param name="Warten"></param>
    ''' <remarks></remarks>
    Protected Sub NaechsterBefehl(ByVal Ziel As Point, ByVal Gegner As ObjektEinheit, ByVal Befehl As KIModiExtern, ByRef WSS As Wegsuchsystem, Optional ByVal Warten As Integer = 2, Optional ByVal Wait As Boolean = True)
        Dim Spielmenue As ObjektSpielMenue = Objektverwalter.Menue
        AktuelleZiel = Ziel
        KIModusEinheitenBefehl = Befehl
        Opfer = Gegner
        If Objektverwalter.Spielfeld.Laufen Is Nothing Then
            If Not Befehl = KIModiExtern.Entladen Then
                WSS.Ziel(Ziel.X, Ziel.Y, True)
                Objektverwalter.Spielfeld.Wegsuchsystem = WSS
                Spielmenue.EinheitBewegungsBefehl(Ziel.X, Ziel.Y)
            End If
        ElseIf Objektverwalter.Spielfeld.Laufen.Position = Ziel Then
            'Wir muessen uns nicht mehr bewegen
        Else
            If Not Befehl = KIModiExtern.Entladen Then
                WSS.Ziel(Ziel.X, Ziel.Y, True)
                Objektverwalter.Spielfeld.Wegsuchsystem = WSS
                Spielmenue.EinheitBewegungsBefehl(Ziel.X, Ziel.Y)
            End If
        End If
        AufBefehlEndeWarten(Befehl, Warten, Wait)
    End Sub
    ''' <summary>
    ''' Fuehrt einen Befehl fuer ein Gebaeude aus.
    ''' </summary>
    ''' <param name="GebaeudeBefehl"></param>
    ''' <param name="Gebaeude"></param>
    ''' <param name="WarteZeit"></param>
    ''' <param name="ZuBauendeEinheit">Fuer manche Befehle ist dies nur eine virtuelle Einheit. Von der die Koordinaten benoetigt werden.</param>
    ''' <remarks></remarks>
    Protected Sub GebaeudeAuswaehlen(ByVal GebaeudeBefehl As KIModiExtern, ByVal Gebaeude As ObjektGebaeude, ByVal ZuBauendeEinheit As ObjektEinheit, Optional ByVal WarteZeit As Integer = 2, Optional ByVal Wait As Boolean = True)
        BauGebaeude = Gebaeude
        Opfer = ZuBauendeEinheit

        AufBefehlEndeWarten(GebaeudeBefehl, WarteZeit, Wait)
    End Sub
    ''' <summary>
    ''' Fuehrt einen Befehl fuer eine Einheit aus fuer die passive KI!
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="Aktion"></param>
    ''' <param name="Gegner"></param>
    ''' <param name="Warten"></param>
    ''' <remarks></remarks>
    Protected Sub Einheitauswaehlen(ByVal Einheit As ObjektEinheit, ByVal WX As Integer(), ByVal WY As Integer(), ByVal Aktion As KIModiExtern, ByVal Gegner As ObjektEinheit, ByRef WSS As Wegsuchsystem, Optional ByVal Warten As Integer = 2, Optional ByVal Wait As Boolean = True)
        If Not Einheit Is Nothing Then
            Objektverwalter.ZuFeldgehen(Einheit.X, Einheit.Y)
            Dim Spielmenue As ObjektSpielMenue = Objektverwalter.Menue
            AktuelleEinheit = Einheit
            AktuelleZiel = New Point(WX(0), WY(0))
            KIModusEinheitenBefehl = Aktion
            Opfer = Gegner
            If Not WSS Is Nothing And Spieler.KIStufe <> ObjektSpieler.KIStufen.Passiv Then
                WSS.Ziel(AktuelleZiel.X, AktuelleZiel.Y, True)
            End If
            Objektverwalter.Einheitauswaehlen(AktuelleEinheit.X, AktuelleEinheit.Y, WSS)
            If WSS Is Nothing Then
                'Die passive KI muss erst noch das Ziel festlegen
                Objektverwalter.Spielfeld.Wegsuchsystem.WegpunkteX = WX
                Objektverwalter.Spielfeld.Wegsuchsystem.WegpunkteY = WY
            End If

            Spielmenue.EinheitBewegungsBefehl(AktuelleZiel.X, AktuelleZiel.Y)

            AufBefehlEndeWarten(Aktion, Warten, Wait)
        End If
    End Sub
#End Region
#Region "Gebaeude Feuer"
    ''' <summary>
    ''' Intelligen Deffence System developed by Robosturm for Intelligent Base Deffence.
    ''' </summary>
    ''' <remarks></remarks>
    Public Function IDSBuildingUse() As Boolean
        Dim NewUnits As Boolean = False
        While MomentaneEinheit < Gebaeude.Length
            Dim MomGebaeude As ObjektGebaeude = Gebaeude(MomentaneEinheit)
            If Not MomGebaeude.GetRealGebaeudeID = "VERWEIS" Then
                If MomGebaeude.Feuerbereit = 0 Then
                    If TypeOf MomGebaeude Is GebaeudeLaser Then
                        If LaserUse(MomGebaeude) Then
                            GebaeudeAuswaehlen(KIModiExtern.Schuss, MomGebaeude, New EinheitAmphibienpanzer(0, 1, 1, False), 4)
                        End If
                    ElseIf TypeOf MomGebaeude Is GebaeudeAruura Then
                        If AzuuraUse(MomGebaeude) Then
                            GebaeudeAuswaehlen(KIModiExtern.Schuss, MomGebaeude, New EinheitAmphibienpanzer(0, 1, 1, False), 4)
                        End If
                    ElseIf TypeOf MomGebaeude Is GebaeudeOmega_Rakete Then
                        Dim Omega As GebaeudeOmega_Rakete = MomGebaeude
                        If Omega.RaketeFeuerbereit = True Then
                            Dim Ziel As Point = GetBestenEinschlagsOrt(Omega.Reichweite, Omega.Schaden)
                            If Ziel.X >= 0 Then
                                GebaeudeAuswaehlen(KIModiExtern.OmegaRaketeStarten, Omega, New EinheitArtillerie(0, Ziel.X, Ziel.Y), 4)
                            End If
                        ElseIf Spieler.Fonds > 30000 Then
                            For I = 0 To Omega.Variablen.Length - 1
                                If Omega.Variablen(I).Wert = 1 Then
                                    'Wir bauen einen Teil der Omega-Rakete
                                    GebaeudeAuswaehlen(KIModiExtern.OmegaUpgradeKaufen, Omega, New EinheitArtillerie(0, I, 0), 4)
                                    Exit For
                                End If
                            Next
                        End If
                        ElseIf TypeOf MomGebaeude Is GebaeudeMonolith Then
                            If CrystallMonolithUse(MomGebaeude) Then
                                GebaeudeAuswaehlen(KIModiExtern.Schuss, MomGebaeude, New EinheitAmphibienpanzer(0, 1, 1, False), 4)
                            End If
                        ElseIf TypeOf MomGebaeude Is GebaeudeKristall Then
                            If CrystallMonolithUse(MomGebaeude) Then
                                GebaeudeAuswaehlen(KIModiExtern.Schuss, MomGebaeude, New EinheitAmphibienpanzer(0, 1, 1, False), 4)
                            End If
                        ElseIf TypeOf MomGebaeude Is GebaeudeSchocklaser_N Then
                            If UseDeathRayNorth(MomGebaeude) Then
                                GebaeudeAuswaehlen(KIModiExtern.Schuss, MomGebaeude, New EinheitAmphibienpanzer(0, 1, 1, False), 4)
                            End If
                        ElseIf TypeOf MomGebaeude Is GebaeudeSchocklaser_W Then
                            If UseDeathRayWest(MomGebaeude) Then
                                GebaeudeAuswaehlen(KIModiExtern.Schuss, MomGebaeude, New EinheitAmphibienpanzer(0, 1, 1, False), 4)
                            End If
                        ElseIf TypeOf MomGebaeude Is GebaeudeSchocklaser_S Then
                            If UseDeathRaySouth(MomGebaeude) Then
                                GebaeudeAuswaehlen(KIModiExtern.Schuss, MomGebaeude, New EinheitAmphibienpanzer(0, 1, 1, False), 4)
                            End If
                        ElseIf TypeOf MomGebaeude Is GebaeudeSchocklaser_O Then
                            If UseDeathRayEast(MomGebaeude) Then
                                GebaeudeAuswaehlen(KIModiExtern.Schuss, MomGebaeude, New EinheitAmphibienpanzer(0, 1, 1, False), 4)
                            End If
                        Else 'A Minicanon or something like this!
                            Dim Ziel As Point = GetBestesGebaeudeFeuer(MomGebaeude)
                            If Ziel.X >= 0 And Ziel.Y >= 0 Then
                                If MomGebaeude.Angriff = ObjektGebaeude.Angriffe.SchussN Or MomGebaeude.Angriff = ObjektGebaeude.Angriffe.SchussW Or MomGebaeude.Angriff = ObjektGebaeude.Angriffe.SchussS Or MomGebaeude.Angriff = ObjektGebaeude.Angriffe.SchussO Then
                                    GebaeudeAuswaehlen(KIModiExtern.Schuss, MomGebaeude, Objektverwalter.Spielfeld.Einheiten(Ziel.X, Ziel.Y, Schlachtfeld), 4)
                                Else
                                    'Wir muessen erst noch eine virtuelle Einheit erschaffen.=)
                                    GebaeudeAuswaehlen(KIModiExtern.Schuss, MomGebaeude, New EinheitAmphibienpanzer(0, Ziel.X, Ziel.Y, False), 4)
                                End If
                            End If
                        End If
                ElseIf TypeOf MomGebaeude Is GebaeudeFabrik Then
                    Dim Y As Integer = MomGebaeude.Rechteck.Y + 2
                    Dim X As Integer = MomGebaeude.Rechteck.X - 1
                    Dim Unit As ObjektEinheit = GetBestFactoryUnit(MomGebaeude)
                    While Unit IsNot Nothing
                        GebaeudeAuswaehlen(KIModiExtern.FabrikBauen, MomGebaeude, Unit, 4)
                        Unit = GetBestFactoryUnit(MomGebaeude)
                        NewUnits = True
                    End While
                End If
            End If
            MomentaneEinheit += 1
        End While
        Return NewUnits
    End Function
    ''' <summary>
    ''' should we use our new Laser system?
    ''' </summary>
    ''' <param name="Laser"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function LaserUse(ByVal Laser As GebaeudeLaser) As Boolean
        Dim FondsDamage As Integer = 0
        For I As Integer = 1 To Laser.Reichweite + 1
            Dim X As Integer = Laser.Rechteck.X - I
            Dim Y As Integer = Laser.Rechteck.Y
            If Objektverwalter.Spielfeld.OnMap(X, Y) Then
                Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If E IsNot Nothing Then
                    If E.GetSpieler.Team = Spieler.Team Then
                        FondsDamage -= E.Kosten * E.GetSpieler.Teurungsrate(E, E.X, E.Y) * 2
                    Else
                        FondsDamage += E.Kosten * E.GetSpieler.Teurungsrate(E, E.X, E.Y)
                    End If
                End If
            End If
        Next
        'Nach links markieren
        For I2 As Integer = 1 To Laser.Reichweite + 1
            Dim X As Integer = Laser.Rechteck.X + I2
            Dim Y As Integer = Laser.Rechteck.Y
            If Objektverwalter.Spielfeld.OnMap(X, Y) Then
                Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If E IsNot Nothing Then
                    If E.GetSpieler.Team = Spieler.Team Then
                        FondsDamage -= E.Kosten * E.GetSpieler.Teurungsrate(E, E.X, E.Y) * 2
                    Else
                        FondsDamage += E.Kosten * E.GetSpieler.Teurungsrate(E, E.X, E.Y)
                    End If
                End If
            End If
        Next
        'Nach oben markieren
        For I3 As Integer = 1 To Laser.Reichweite + 1
            Dim X As Integer = Laser.Rechteck.X
            Dim Y As Integer = Laser.Rechteck.Y - I3
            If Objektverwalter.Spielfeld.OnMap(X, Y) Then
                Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If E IsNot Nothing Then
                    If E.GetSpieler.Team = Spieler.Team Then
                        FondsDamage -= E.Kosten * E.GetSpieler.Teurungsrate(E, E.X, E.Y) * 2
                    Else
                        FondsDamage += E.Kosten * E.GetSpieler.Teurungsrate(E, E.X, E.Y)
                    End If
                End If
            End If
        Next
        'Nach unten markiern
        For I4 As Integer = 1 To Laser.Reichweite + 1
            Dim X As Integer = Laser.Rechteck.X
            Dim Y As Integer = Laser.Rechteck.Y + I4
            If Objektverwalter.Spielfeld.OnMap(X, Y) Then
                Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlachtfeld)
                If E IsNot Nothing Then
                    If E.GetSpieler.Team = Spieler.Team Then
                        FondsDamage -= E.Kosten * E.GetSpieler.Teurungsrate(E, E.X, E.Y) * 2
                    Else
                        FondsDamage += E.Kosten * E.GetSpieler.Teurungsrate(E, E.X, E.Y)
                    End If
                End If
            End If
        Next
        If FondsDamage > 0 Then
            Return True
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Produces the best Unit for this Factory!!!
    ''' </summary>
    ''' <param name="Factory"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetBestFactoryUnit(ByVal Factory As GebaeudeFabrik) As ObjektEinheit
        Dim Unit As ObjektEinheit = Nothing
        If Factory.Variablen(1).Wert > 0 Then
            If Factory.Variablen(0).Wert > 0 Then
                Dim Tor As Integer = Factory.Variablen(0).Wert
                'Finding the next production Door
                Dim TotalDamage As Int64 = -1
                If Tor >= 4 Then
                    Dim NewDamage As Int64 = 0
                    Dim E As ObjektEinheit = GetBestUnitForDoor(Factory, 1, NewDamage)
                    If NewDamage > TotalDamage Or TotalDamage < 0 Then
                        TotalDamage = NewDamage
                        Unit = E
                    End If
                    Tor -= 4
                End If
                If Tor >= 2 Then
                    Dim NewDamage As Int64 = 0
                    Dim E As ObjektEinheit = GetBestUnitForDoor(Factory, 0, NewDamage)
                    If NewDamage > TotalDamage Or TotalDamage < 0 Then
                        TotalDamage = NewDamage
                        Unit = E
                    End If
                    Tor -= 2
                End If
                If Tor >= 1 Then
                    Dim NewDamage As Int64 = 0
                    Dim E As ObjektEinheit = GetBestUnitForDoor(Factory, -1, NewDamage)
                    If NewDamage > TotalDamage Or TotalDamage < 0 Then
                        TotalDamage = NewDamage
                        Unit = E
                    End If
                    Tor -= 1
                End If
            End If
        End If
        Return Unit
    End Function
    ''' <summary>
    ''' Let's see what can came out here.
    ''' </summary>
    ''' <param name="Factory"></param>
    ''' <param name="Door">-1,0,1</param>
    ''' <param name="TotalDamage"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetBestUnitForDoor(ByVal Factory As GebaeudeFabrik, ByVal Door As Integer, ByRef TotalDamage As Int64) As ObjektEinheit
        Dim Units As String() = Factory.GetBauEinheiten(Factory.Rechteck.X + Door, Factory.Rechteck.Y + 2)
        Dim Unit As ObjektEinheit = Nothing
        For I = 0 To Units.Length - 1
            Dim E As ObjektEinheit = ObjektLadeklasse.NewEinheit(Units(I), Factory.Spieler, Factory.Rechteck.X + Door, Factory.Rechteck.Y + 2, False)
            Dim NewDamage As Int64 = KIGenerellerSuperBau.CalculateDamage(E)
            If NewDamage > TotalDamage Or TotalDamage < 0 Then
                Unit = E
                TotalDamage = NewDamage
            End If
        Next
        Return Unit
    End Function
    ''' <summary>
    ''' Oh yeah! Let's use a Monolith or Crystall right now?
    ''' </summary>
    ''' <param name="Gebaeude"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function CrystallMonolithUse(ByVal Gebaeude As ObjektGebaeude) As Boolean
        Dim Kreis(,) As Integer = Kreisfunktion(Gebaeude.Reichweite)
        For X = 0 To Kreis.GetLength(0) - 1
            For Y = 0 To Kreis.GetLength(1) - 1
                If Kreis(X, Y) > 0 Then
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Gebaeude.Rechteck.X - Gebaeude.Reichweite + X, Gebaeude.Rechteck.Y - Gebaeude.Reichweite + Y, Schlachtfeld)
                    If E IsNot Nothing Then
                        If E.Spieler = Gebaeude.Spieler Then
                            If E.Munition < E.MunitionMax Or E.Treibstoff < E.SpritMax Then
                                Return True
                            ElseIf E.getKP < 8 Then
                                Return True
                            End If
                        End If
                    End If
                End If
            Next
        Next
        Return False
    End Function
    ''' <summary>
    ''' Oh yeah! Let's use a Monolith or Crystall right now?
    ''' </summary>
    ''' <param name="Gebaeude"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function AzuuraUse(ByVal Gebaeude As ObjektGebaeude) As Boolean
        Dim Kreis(,) As Integer = Kreisfunktion(Gebaeude.Reichweite)
        For X = 0 To Kreis.GetLength(0) - 1
            For Y = 0 To Kreis.GetLength(1) - 1
                If Kreis(X, Y) > 0 Then
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Gebaeude.Rechteck.X - Gebaeude.Reichweite + X, Gebaeude.Rechteck.Y - Gebaeude.Reichweite + Y, Schlachtfeld)
                    If E IsNot Nothing Then
                        If E.GetSpieler.Team <> Gebaeude.GetSpieler.Team Then
                            Return True
                        End If
                    End If
                End If
            Next
        Next
        Return False
    End Function
    ''' <summary>
    ''' Should we use this Death Ray!
    ''' </summary>
    ''' <param name="DeathRay"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function UseDeathRayNorth(ByVal DeathRay As GebaeudeSchocklaser_N, Optional ByVal Damage As Integer = 10000) As Boolean
        Dim D As Int64 = 0
        For Y = -DeathRay.Reichweite To -2
            For X = -1 To 1
                Dim X1 As Integer = DeathRay.Rechteck.X + X
                Dim Y1 As Integer = DeathRay.Rechteck.Y + Y
                If Objektverwalter.Spielfeld.OnMap(X1, Y1) Then
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X1, Y1, Schlachtfeld)
                    If E IsNot Nothing Then
                        If E.GetSpieler.Team <> Spieler.Team Then
                            D += E.Kosten * E.GetSpieler.Teurungsrate(E.EinheitenID, X1, Y1)
                        End If
                    End If
                End If
            Next
        Next
        If D > Damage Then
            Return True
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Should we use this Death Ray!
    ''' </summary>
    ''' <param name="DeathRay"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function UseDeathRayWest(ByVal DeathRay As GebaeudeSchocklaser_W, Optional ByVal Damage As Integer = 10000) As Boolean
        Dim D As Int64 = 0
        For X = -DeathRay.Reichweite To -2
            For Y = -1 To 1
                Dim X1 As Integer = DeathRay.Rechteck.X + X
                Dim Y1 As Integer = DeathRay.Rechteck.Y + Y
                If Objektverwalter.Spielfeld.OnMap(X1, Y1) Then
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X1, Y1, Schlachtfeld)
                    If E IsNot Nothing Then
                        If E.GetSpieler.Team <> Spieler.Team Then
                            D += E.Kosten * E.GetSpieler.Teurungsrate(E.EinheitenID, X1, Y1)
                        End If
                    End If
                End If
            Next
        Next
        If D > Damage Then
            Return True
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Should we use this Death Ray!
    ''' </summary>
    ''' <param name="DeathRay"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function UseDeathRayEast(ByVal DeathRay As GebaeudeSchocklaser_O, Optional ByVal Damage As Integer = 10000) As Boolean
        Dim D As Int64 = 0
        For X = 2 To DeathRay.Reichweite
            For Y = -1 To 1
                Dim X1 As Integer = DeathRay.Rechteck.X + X
                Dim Y1 As Integer = DeathRay.Rechteck.Y + Y
                If Objektverwalter.Spielfeld.OnMap(X1, Y1) Then
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X1, Y1, Schlachtfeld)
                    If E IsNot Nothing Then
                        If E.GetSpieler.Team <> Spieler.Team Then
                            D += E.Kosten * E.GetSpieler.Teurungsrate(E.EinheitenID, X1, Y1)
                        End If
                    End If
                End If
            Next
        Next
        If D > Damage Then
            Return True
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Should we use this Death Ray!
    ''' </summary>
    ''' <param name="DeathRay"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function UseDeathRaySouth(ByVal DeathRay As GebaeudeSchocklaser_S, Optional ByVal Damage As Integer = 10000) As Boolean
        Dim D As Int64 = 0
        For Y = 2 To DeathRay.Reichweite
            For X = -1 To 1
                Dim X1 As Integer = DeathRay.Rechteck.X + X
                Dim Y1 As Integer = DeathRay.Rechteck.Y + Y
                If Objektverwalter.Spielfeld.OnMap(X1, Y1) Then
                    Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X1, Y1, Schlachtfeld)
                    If E IsNot Nothing Then
                        If E.GetSpieler.Team <> Spieler.Team Then
                            D += E.Kosten * E.GetSpieler.Teurungsrate(E.EinheitenID, X1, Y1)
                        End If
                    End If
                End If
            Next
        Next
        If D > Damage Then
            Return True
        Else
            Return False
        End If
    End Function
#End Region
#Region "Nebel"

    ''' <summary>
    ''' Erschafft das Sichtfeld fuer eine Einheit.
    ''' </summary>
    ''' <param name="Einheit"></param>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <remarks></remarks>
    Public Shared Sub CreateEinheitenSicht(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer, ByVal Schlachtfeld As Integer, ByVal Spieler As ObjektSpieler, ByRef Sichtfeld(,,) As Boolean, ByVal HumanPlayer As Boolean)
        Dim Sicht As Integer = Einheit.GetSicht(X, Y)
        If Objektverwalter.Spielfeld.Spieler(Einheit.Spieler).VeraenderteWerte.SichtradiusVeraenderung > 0 Then
            Sicht = Objektverwalter.Spielfeld.Spieler(Einheit.Spieler).VeraenderteWerte.SichtradiusVeraenderung
        End If
        Dim Kreis(,) As Integer = Kreisfunktion(Sicht)
        For X1 = 0 To Kreis.GetLength(0) - 1
            For Y1 = 0 To Kreis.GetLength(1) - 1
                If Objektverwalter.Spielfeld.OnMap(X - Sicht + X1, Y - Sicht + Y1) Then
                    If Kreis(X1, Y1) >= 0 Then
                        If Kreis(X1, Y1) <= 1 Then
                            Sichtfeld(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld) = True
                            If HumanPlayer Then
                                Objektverwalter.Spielfeld.Landschaften(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld).Kriegsnebel = Nebelarten.Aus
                                If Objektverwalter.Spielfeld.Einheiten(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld) IsNot Nothing Then
                                    Objektverwalter.Spielfeld.Einheiten(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld).Sichtbar = True
                                End If
                            End If
                        Else
                            If Objektverwalter.Spielfeld.Landschaften(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld).Tarnung = False Then
                                If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld)) = False Then
                                    If Objektverwalter.Spielfeld.Einheiten(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld).IsGetarnt(Spieler.Spieler) = False Then
                                        Sichtfeld(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld) = True
                                        If HumanPlayer Then
                                            Objektverwalter.Spielfeld.Landschaften(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld).Kriegsnebel = Nebelarten.Aus
                                            Objektverwalter.Spielfeld.Einheiten(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld).Sichtbar = True
                                        End If
                                    End If
                                Else
                                    Sichtfeld(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld) = True
                                    If HumanPlayer Then
                                        Objektverwalter.Spielfeld.Landschaften(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld).Kriegsnebel = Nebelarten.Aus
                                    End If
                                End If
                            ElseIf Objektverwalter.Spielfeld.Spieler(Einheit.Spieler).KOS(0).RiffWaldSchauer = True Then
                                If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld)) = False Then
                                    If Objektverwalter.Spielfeld.Einheiten(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld).IsGetarnt(Spieler.Spieler) = False Then
                                        Sichtfeld(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld) = True
                                        If HumanPlayer Then
                                            Objektverwalter.Spielfeld.Landschaften(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld).Kriegsnebel = Nebelarten.Aus
                                            Objektverwalter.Spielfeld.Einheiten(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld).Sichtbar = True
                                        End If
                                    End If
                                Else
                                    Sichtfeld(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld) = True
                                    If HumanPlayer Then
                                        Objektverwalter.Spielfeld.Landschaften(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld).Kriegsnebel = Nebelarten.Aus
                                    End If
                                End If
                            Else
                                If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld)) = False Then
                                    If Objektverwalter.Spielfeld.Einheiten(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld).IsFlyingUnit Then
                                        If Objektverwalter.Spielfeld.Einheiten(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld).IsGetarnt(Spieler.Spieler) = False Then
                                            Sichtfeld(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld) = True
                                            If HumanPlayer Then
                                                Objektverwalter.Spielfeld.Landschaften(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld).Kriegsnebel = Nebelarten.Aus
                                                Objektverwalter.Spielfeld.Einheiten(X - Sicht + X1, Y - Sicht + Y1, Schlachtfeld).Sichtbar = True
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    End If
                End If
            Next
        Next
    End Sub
    ''' <summary>
    ''' Erstellt die Sicht von Radar Gebaeuden
    ''' </summary>
    ''' <param name="G"></param>
    ''' <remarks></remarks>
    Protected Shared Sub CreateGebaeudeSicht(ByVal G As ObjektGebaeude, ByVal Schlachtfeld As Integer, ByVal Spieler As ObjektSpieler, ByRef Sichtfeld(,,) As Boolean, ByVal HumanPlayer As Boolean)
        Dim Radius As Integer
        Select Case Objektverwalter.Spielfeld.GetCommanderWarsModus
            Case CommanderWarsGameModi.AdvanceWarsDC
                Radius = 2
            Case Else
                Radius = -1
        End Select
        If G.Angriff = ObjektGebaeude.Angriffe.Radar Then Radius = G.Reichweite
        Dim X As Integer = G.Rechteck.X
        Dim Y As Integer = G.Rechteck.Y
        Dim Kreis(,) As Integer = Kreisfunktion(Radius)
        If Radius >= 0 Then
            For X1 = 0 To Kreis.GetLength(0) - 1
                For Y1 = 0 To Kreis.GetLength(1) - 1
                    If Objektverwalter.Spielfeld.OnMap(X - Radius + X1, Y - Radius + Y1) Then
                        If Kreis(X1, Y1) > 0 Then
                            If Objektverwalter.Spielfeld.Landschaften(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).Tarnung = False Then
                                If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld)) = False Then
                                    If Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).IsGetarnt(Spieler.Spieler) = False Then
                                        Sichtfeld(X - Radius + X1, Y - Radius + Y1, Schlachtfeld) = True
                                        If HumanPlayer Then
                                            Objektverwalter.Spielfeld.Landschaften(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).Kriegsnebel = Nebelarten.Aus
                                            Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).Sichtbar = True
                                        End If
                                    End If
                                Else
                                    Sichtfeld(X - Radius + X1, Y - Radius + Y1, Schlachtfeld) = True
                                    If HumanPlayer Then
                                        Objektverwalter.Spielfeld.Landschaften(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).Kriegsnebel = Nebelarten.Aus
                                    End If
                                End If
                            ElseIf Objektverwalter.Spielfeld.Spieler(G.Spieler).KOS(0).RiffWaldSchauer = True Then
                                If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld)) = False Then
                                    If Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).IsGetarnt(Spieler.Spieler) = False Then
                                        Sichtfeld(X - Radius + X1, Y - Radius + Y1, Schlachtfeld) = True
                                        If HumanPlayer Then
                                            Objektverwalter.Spielfeld.Landschaften(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).Kriegsnebel = Nebelarten.Aus
                                            Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).Sichtbar = True
                                        End If
                                    End If
                                Else
                                    Sichtfeld(X - Radius + X1, Y - Radius + Y1, Schlachtfeld) = True
                                    If HumanPlayer Then
                                        Objektverwalter.Spielfeld.Landschaften(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).Kriegsnebel = Nebelarten.Aus
                                    End If
                                End If
                            Else
                                If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld)) = False Then
                                    If Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).Bewegungsart = MovementSorts.Helikopter.ToString Or Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).Bewegungsart = MovementSorts.Flugzeug.ToString Then
                                        If Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).IsGetarnt(Spieler.Spieler) = False Then
                                            Sichtfeld(X - Radius + X1, Y - Radius + Y1, Schlachtfeld) = True
                                            If HumanPlayer Then
                                                Objektverwalter.Spielfeld.Landschaften(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).Kriegsnebel = Nebelarten.Aus
                                                Objektverwalter.Spielfeld.Einheiten(X - Radius + X1, Y - Radius + Y1, Schlachtfeld).Sichtbar = True
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        End If
    End Sub
    ''' <summary>
    ''' Erstellt die Sicht der Landschaft Feuer
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <param name="Sichtweite"></param>
    ''' <remarks></remarks>
    Protected Shared Sub CreateFeuerSicht(ByVal X As Integer, ByVal Y As Integer, ByVal Sichtweite As Integer, ByVal Schlachtfeld As Integer, ByVal Spieler As ObjektSpieler, ByRef Sichtfeld(,,) As Boolean, ByVal HumanPlayer As Boolean)
        Dim Kreis(,) As Integer = Kreisfunktion(Sichtweite)
        For X1 = 0 To Kreis.GetLength(0) - 1
            For Y1 = 0 To Kreis.GetLength(1) - 1
                If Kreis(X1, Y1) >= 0 Then
                    If Objektverwalter.Spielfeld.OnMap(X - Sichtweite + X1, Y - Sichtweite + Y1) Then
                        If Objektverwalter.Spielfeld.Landschaften(X - Sichtweite + X1, Y - Sichtweite + Y1, Schlachtfeld).Tarnung = False Then
                            If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - Sichtweite + X1, Y - Sichtweite + Y1, Schlachtfeld)) = False Then
                                If Objektverwalter.Spielfeld.Einheiten(X - Sichtweite + X1, Y - Sichtweite + Y1, Schlachtfeld).IsGetarnt(Spieler.Spieler) = False Then
                                    Sichtfeld(X - Sichtweite + X1, Y - Sichtweite + Y1, Schlachtfeld) = True
                                    If HumanPlayer Then
                                        Objektverwalter.Spielfeld.Landschaften(X - Sichtweite + X1, Y - Sichtweite + Y1, Schlachtfeld).Kriegsnebel = Nebelarten.Aus
                                        If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - Sichtweite + X1, Y - Sichtweite + Y1, Schlachtfeld)) = False Then
                                            Objektverwalter.Spielfeld.Einheiten(X - Sichtweite + X1, Y - Sichtweite + Y1, Schlachtfeld).Sichtbar = True
                                        End If
                                    End If
                                End If
                            Else
                                Sichtfeld(X - Sichtweite + X1, Y - Sichtweite + Y1, Schlachtfeld) = True
                                If HumanPlayer Then
                                    Objektverwalter.Spielfeld.Landschaften(X - Sichtweite + X1, Y - Sichtweite + Y1, Schlachtfeld).Kriegsnebel = Nebelarten.Aus
                                    If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - Sichtweite + X1, Y - Sichtweite + Y1, Schlachtfeld)) = False Then
                                        Objektverwalter.Spielfeld.Einheiten(X - Sichtweite + X1, Y - Sichtweite + Y1, Schlachtfeld).Sichtbar = True
                                    End If
                                End If
                            End If
                        End If
                    End If
                End If
            Next
        Next
    End Sub
    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <param name="Reichweite"></param>
    ''' <param name="Alles">Wenn true werden auch alle Waelder aufgedeckt</param>
    ''' <remarks></remarks>
    Protected Shared Sub UnfogArea(ByVal X As Integer, ByVal Y As Integer, ByVal Reichweite As Integer, ByVal Alles As Boolean, ByVal Schlachtfeld As Integer, ByVal Spieler As ObjektSpieler, ByRef Sichtfeld(,,) As Boolean, ByVal HumanPlayer As Boolean)
        Dim Kreis(,) As Integer = Kreisfunktion(Reichweite)
        For X1 = 0 To Kreis.GetLength(0) - 1
            For Y1 = 0 To Kreis.GetLength(1) - 1
                If Objektverwalter.Spielfeld.OnMap(X - Reichweite + X1, Y - Reichweite + Y1) Then
                    If Kreis(X1, Y1) > 0 Then
                        If Kreis(X1, Y1) > 0 Then
                            If Objektverwalter.Spielfeld.Landschaften(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld).Tarnung = False Or Alles = True Then

                                If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld)) = False Then
                                    If Objektverwalter.Spielfeld.Einheiten(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld).IsGetarnt(Spieler.Spieler) = False Then
                                        'Einheit und Landschaft sind sichtbar
                                        Sichtfeld(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld) = True
                                        If HumanPlayer Then
                                            Objektverwalter.Spielfeld.Landschaften(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld).Kriegsnebel = Nebelarten.Aus
                                            Objektverwalter.Spielfeld.Einheiten(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld).Sichtbar = True
                                        End If
                                    End If
                                Else
                                    'Nur Landschaft da keine Einheit drauf steht
                                    Sichtfeld(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld) = True
                                    If HumanPlayer Then
                                        Objektverwalter.Spielfeld.Landschaften(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld).Kriegsnebel = Nebelarten.Aus
                                    End If
                                End If
                            ElseIf Objektverwalter.Spielfeld.Spieler(Spieler.Spieler).KOS(0).RiffWaldSchauer = True Then
                                If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld)) = False Then
                                    If Objektverwalter.Spielfeld.Einheiten(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld).IsGetarnt(Spieler.Spieler) = False Then
                                        'Einheit und Landschaft sind sichtbar
                                        Sichtfeld(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld) = True
                                        If HumanPlayer Then
                                            Objektverwalter.Spielfeld.Landschaften(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld).Kriegsnebel = Nebelarten.Aus
                                            Objektverwalter.Spielfeld.Einheiten(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld).Sichtbar = True
                                        End If
                                    End If
                                Else
                                    'Nur Landschaft da keine Einheit drauf steht
                                    Sichtfeld(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld) = True
                                    If HumanPlayer Then
                                        Objektverwalter.Spielfeld.Landschaften(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld).Kriegsnebel = Nebelarten.Aus
                                    End If
                                End If
                            Else
                                If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld)) = False Then
                                    If Objektverwalter.Spielfeld.Einheiten(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld).Bewegungsart = MovementSorts.Helikopter.ToString Or Objektverwalter.Spielfeld.Einheiten(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld).Bewegungsart = MovementSorts.Flugzeug.ToString Then
                                        If Objektverwalter.Spielfeld.Einheiten(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld).IsGetarnt(Spieler.Spieler) = False Then
                                            Sichtfeld(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld) = True
                                            If HumanPlayer Then
                                                Objektverwalter.Spielfeld.Landschaften(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld).Kriegsnebel = Nebelarten.Aus
                                                Objektverwalter.Spielfeld.Einheiten(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld).Sichtbar = True
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    ElseIf Kreis(X1, Y1) = 0 Then
                        Sichtfeld(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld) = True
                        If HumanPlayer Then
                            Objektverwalter.Spielfeld.Landschaften(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld).Kriegsnebel = Nebelarten.Aus
                            If IsNothing(Objektverwalter.Spielfeld.Einheiten(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld)) = False Then
                                Objektverwalter.Spielfeld.Einheiten(X - Reichweite + X1, Y - Reichweite + Y1, Schlachtfeld).Sichtbar = True
                            End If
                        End If
                    End If
                End If
            Next
        Next
    End Sub
    ''' <summary>
    ''' Erstellt die Landschaften die der Spieler sehen kann
    ''' </summary>
    ''' <remarks></remarks>
    Public Shared Sub CreateSicht(ByRef Sichtfeld(,,) As Boolean, ByVal Spieler As ObjektSpieler, Optional ByVal HumanPlayer As Boolean = False, Optional ByVal ResetNebel As Boolean = False)
        Dim RegenNebel As Boolean = False
        Select Case Objektverwalter.Spielfeld.GetCommanderWarsModus
            Case CommanderWarsGameModi.CommanderWars2
                If Objektverwalter.Spielfeld.Regeln.Wetter = ObjektSpielfeld.Wetterarten.Regen Then
                    If Not Spieler.KOS(0).Wetterimmunitaet.Contains(ObjektSpielfeld.Wetterarten.Regen) Then
                        RegenNebel = True
                    End If
                End If
            Case CommanderWarsGameModi.AdvanceWarsDS, CommanderWarsGameModi.AdvanceWarsDC
                If Objektverwalter.Spielfeld.Regeln.Wetter = ObjektSpielfeld.Wetterarten.Regen Then
                    'In DS und DC muessen wir jetzt Nebel erzeugen.
                    'Ich will aber nicht.
                    'Hier geht es nicht um wollen sondern um die Regeln. Doof!
                    If Not Spieler.KOS(0).Wetterimmunitaet.Contains(ObjektSpielfeld.Wetterarten.Regen) Then
                        RegenNebel = True
                    End If
                End If
        End Select
        Dim PermanenteAufdeckung As Boolean = Objektverwalter.Spielfeld.IsPermanenteAufdeckung

        If Not PermanenteAufdeckung Or ResetNebel Then
            For NebelSchlachtfeld = 0 To ObjektSpielfeld.Luftschlacht
                If Objektverwalter.Spielfeld.Regeln.NebelFelder IsNot Nothing Then
                    For Each NebelFeld In Objektverwalter.Spielfeld.Regeln.NebelFelder
                        If Objektverwalter.Spielfeld.OnMap(NebelFeld.X, NebelFeld.Y, True) Then
                            If Spieler.Spieler = NebelFeld.Spieler Or NebelFeld.Spieler <= 0 Then
                                Sichtfeld(NebelFeld.X, NebelFeld.Y, NebelSchlachtfeld) = False
                                Objektverwalter.Spielfeld.Landschaften(NebelFeld.X, NebelFeld.Y, NebelSchlachtfeld).Kriegsnebel = NebelFeld.Nebel
                            End If
                        End If
                    Next
                End If
                For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                    For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                        If Not Objektverwalter.Spielfeld.Landschaften(X, Y, NebelSchlachtfeld).Hidden Then
                            If Objektverwalter.Spielfeld.Regeln.ContainsNebelfeld(X, Y, Spieler.Spieler) < 0 Then
                                If Objektverwalter.Spielfeld.Regeln.Nebel > 0 Or RegenNebel Then
                                    Sichtfeld(X, Y, NebelSchlachtfeld) = False
                                    If HumanPlayer Then
                                        If RegenNebel Then
                                            Objektverwalter.Spielfeld.Landschaften(X, Y, NebelSchlachtfeld).Kriegsnebel = Nebelarten.Kriegsnebel
                                        Else
                                            Objektverwalter.Spielfeld.Landschaften(X, Y, NebelSchlachtfeld).Kriegsnebel = Objektverwalter.Spielfeld.Regeln.Nebel
                                        End If
                                        If IsNothing(Objektverwalter.Spielfeld.Einheiten(X, Y, NebelSchlachtfeld)) = False Then
                                            Objektverwalter.Spielfeld.Einheiten(X, Y, NebelSchlachtfeld).Sichtbar = False
                                        End If
                                    End If
                                ElseIf Not Objektverwalter.Spielfeld.Einheiten(X, Y, NebelSchlachtfeld) Is Nothing Then
                                    If Objektverwalter.Spielfeld.Einheiten(X, Y, NebelSchlachtfeld).IsGetarnt(Spieler.Spieler) = True Then
                                        Sichtfeld(X, Y, NebelSchlachtfeld) = False
                                        If HumanPlayer Then
                                            Objektverwalter.Spielfeld.Einheiten(X, Y, NebelSchlachtfeld).Sichtbar = False
                                            Objektverwalter.Spielfeld.Landschaften(X, Y, NebelSchlachtfeld).Kriegsnebel = Nebelarten.Aus
                                        End If
                                    Else
                                        Sichtfeld(X, Y, NebelSchlachtfeld) = True
                                        If HumanPlayer Then
                                            Objektverwalter.Spielfeld.Einheiten(X, Y, NebelSchlachtfeld).Sichtbar = True
                                            Objektverwalter.Spielfeld.Landschaften(X, Y, NebelSchlachtfeld).Kriegsnebel = Nebelarten.Aus
                                        End If
                                    End If
                                Else
                                    Sichtfeld(X, Y, NebelSchlachtfeld) = True
                                    If HumanPlayer Then
                                        Objektverwalter.Spielfeld.Landschaften(X, Y, NebelSchlachtfeld).Kriegsnebel = Nebelarten.Aus
                                    End If
                                End If
                            End If
                        End If
                    Next
                Next
            Next
        End If
        For NebelSchlachtfeld = 0 To ObjektSpielfeld.Luftschlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, NebelSchlachtfeld).Hidden Then
                        If IsNothing(Objektverwalter.Spielfeld.Landschaften(X, Y, NebelSchlachtfeld).Gebaeude) = False Then
                            If Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Landschaften(X, Y, NebelSchlachtfeld).Gebaeude.Spieler).Team = Spieler.Team Then
                                Sichtfeld(X, Y, NebelSchlachtfeld) = True
                                If HumanPlayer Then
                                    Objektverwalter.Spielfeld.Landschaften(X, Y, NebelSchlachtfeld).Kriegsnebel = Nebelarten.Aus
                                    If IsNothing(Objektverwalter.Spielfeld.Einheiten(X, Y, NebelSchlachtfeld)) = False Then
                                        Objektverwalter.Spielfeld.Einheiten(X, Y, NebelSchlachtfeld).Sichtbar = True
                                    End If
                                End If
                                CreateGebaeudeSicht(Objektverwalter.Spielfeld.Landschaften(X, Y, NebelSchlachtfeld).Gebaeude, NebelSchlachtfeld, Spieler, Sichtfeld, HumanPlayer)
                            End If
                        End If
                        If Objektverwalter.Spielfeld.Landschaften(X, Y, NebelSchlachtfeld).LandschaftsID = "FEUER" Then
                            CreateFeuerSicht(X, Y, LandschaftsTexturFeuer.FeuerSicht, NebelSchlachtfeld, Spieler, Sichtfeld, HumanPlayer)
                        End If
                        If Objektverwalter.Spielfeld.CurrentAI IsNot Nothing And Not HumanPlayer Then
                            If IsNothing(Objektverwalter.Spielfeld.CurrentAI.AktuelleEinheit) Then
                                If IsNothing(Objektverwalter.Spielfeld.Einheiten(X, Y, NebelSchlachtfeld)) = False Then
                                    If Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Einheiten(X, Y, NebelSchlachtfeld).Spieler).Team = Spieler.Team Then
                                        CreateEinheitenSicht(Objektverwalter.Spielfeld.Einheiten(X, Y, NebelSchlachtfeld), X, Y, NebelSchlachtfeld, Spieler, Sichtfeld, HumanPlayer)
                                    End If
                                End If
                            ElseIf X = Objektverwalter.Spielfeld.CurrentAI.AktuelleEinheit.X And Y = Objektverwalter.Spielfeld.CurrentAI.AktuelleEinheit.Y Then
                            ElseIf X = Objektverwalter.Spielfeld.CurrentAI.AktuelleZiel.X And Y = Objektverwalter.Spielfeld.CurrentAI.AktuelleZiel.Y Then
                                CreateEinheitenSicht(Objektverwalter.Spielfeld.CurrentAI.AktuelleEinheit, Objektverwalter.Spielfeld.CurrentAI.AktuelleZiel.X, Objektverwalter.Spielfeld.CurrentAI.AktuelleZiel.Y, NebelSchlachtfeld, Spieler, Sichtfeld, HumanPlayer)
                            ElseIf IsNothing(Objektverwalter.Spielfeld.Einheiten(X, Y, NebelSchlachtfeld)) = False Then
                                If Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Einheiten(X, Y, NebelSchlachtfeld).Spieler).Team = Spieler.Team Then
                                    CreateEinheitenSicht(Objektverwalter.Spielfeld.Einheiten(X, Y, NebelSchlachtfeld), X, Y, NebelSchlachtfeld, Spieler, Sichtfeld, HumanPlayer)
                                End If
                            End If
                        ElseIf IsNothing(Objektverwalter.Spielfeld.Einheiten(X, Y, NebelSchlachtfeld)) = False Then
                            If Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Einheiten(X, Y, NebelSchlachtfeld).Spieler).Team = Spieler.Team Then
                                CreateEinheitenSicht(Objektverwalter.Spielfeld.Einheiten(X, Y, NebelSchlachtfeld), X, Y, NebelSchlachtfeld, Spieler, Sichtfeld, HumanPlayer)
                            End If
                        End If
                    End If
                Next
            Next
        Next
        For NebelSchlachtfeld = 0 To ObjektSpielfeld.Luftschlacht
            If Spieler.Sichtfelder IsNot Nothing Then
                For I = 0 To Spieler.Sichtfelder.Length - 1
                    If Spieler.Sichtfelder(I).Z = NebelSchlachtfeld Then
                        UnfogArea(Spieler.Sichtfelder(I).X, Spieler.Sichtfelder(I).Y, Spieler.Sichtfelder(I).W, True, NebelSchlachtfeld, Spieler, Sichtfeld, HumanPlayer)
                    End If
                Next
            Else
                Konsole.Write("Error no Player Vision set. Continuing happily!")
            End If
        Next

    End Sub
#End Region
#Region "AI Setting Use for Editor AI"
    ''' <summary>
    ''' Moves all Units without the AI-Setting Standard
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub MoveAIUnits()
        For Each Unit In Einheiten
            If Unit.HatsichBewegt = False Then
                If ExistUnit(Unit) = True Then
                    Select Case Unit.AIUse
                        Case ObjektEinheit.AISetting.Aggresiv
                            PredeployedMoveAllOut(Unit)
                        Case ObjektEinheit.AISetting.Deffensiv
                            PredeployedMoveWaitForAttack(Unit)
                        Case ObjektEinheit.AISetting.Halten
                            PredeployedMoveStop(Unit)
                        Case Else 'Normal AI Use
                    End Select
                    If Unit.AIUse <> ObjektEinheit.AISetting.Standard Then
                        If Unit.HatsichBewegt = False Then
                            Einheitauswaehlen(Unit, Unit.GetLocation, KIModiExtern.Warten, Nothing, Nothing)
                        End If
                    End If
                End If
            End If
        Next
    End Sub
    ''' <summary>
    ''' Moves the Unit for all Out
    ''' </summary>
    ''' <param name="Unit"></param>
    ''' <remarks></remarks>
    Private Sub PredeployedMoveAllOut(ByVal Unit As ObjektEinheit)
        If Unit.HatsichBewegt = False Then
            If Unit.MaximaleReichweite > 1 Then
                Dim WSS As Wegsuchsystem = CreateWSS(Unit)
                'OH je  das wird noch komplikate
                If Unit.CanIndirectMoveAndFire = True And Spieler.KOS(0).FireandMove = True Then
                    Dim Feld As Point = GetBestesFernkampfOpfer(Unit)
                    If Feld.X >= 0 Then
                        Einheitauswaehlen(Unit, New Point(Unit.X, Unit.Y), KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Feld.X, Feld.Y, Schlachtfeld), WSS)
                        Dim Felder As Point2 = GetBestesFernkampfFeldmitBewegung(Unit, WSS)
                        If Felder.Point1.X >= 0 And Felder.Point2.X >= 0 Then
                            'So wir haben ein Opfer.
                            NaechsterBefehl(Felder.Point1, Objektverwalter.Spielfeld.Einheiten(Felder.Point2.X, Felder.Point2.Y, Schlachtfeld), KIModiExtern.Angriff, WSS, 4)
                        End If
                    Else
                        Dim Felder As Point2 = GetBestesFernkampfFeldmitBewegung(Unit, WSS)
                        If Felder.Point1.X >= 0 And Felder.Point2.X >= 0 Then
                            'So wir haben ein Opfer.
                            Einheitauswaehlen(Unit, Felder.Point1, KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Felder.Point2.X, Felder.Point2.Y, Schlachtfeld), WSS)
                        Else

                        End If
                    End If
                    EinheitAbwaehlen()
                ElseIf Unit.CanIndirectMoveAndFire Then
                    'Ein Angriff ziehen und Feuern wie beim Nahkampf
                    Dim Felder As Point2 = GetBestesFernkampfFeldmitBewegung(Unit, WSS)
                    If Felder.Point1.X >= 0 And Felder.Point2.X >= 0 Then
                        'So wir haben ein Opfer.
                        Einheitauswaehlen(Unit, Felder.Point1, KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Felder.Point2.X, Felder.Point2.Y, Schlachtfeld), WSS)
                    End If
                ElseIf Spieler.KOS(0).FireandMove = True Then
                    'Wir suchen uns ein Opfer
                    Dim Feld As Point = GetBestesFernkampfOpfer(Unit)
                    If Feld.X >= 0 Then
                        Einheitauswaehlen(Unit, New Point(Unit.X, Unit.Y), KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Feld.X, Feld.Y, Schlachtfeld), WSS)
                    End If
                    'wir haben unser Opfer angegriffen jetzt sollten wir die Einheit noch ziehen.
                    WSS = New Wegsuchsystem(Unit, Unit.X, Unit.Y, Einheiten(MomentaneEinheit).GetMap, -1)
                    Dim Ziel As Point = GetNaehestesFernkampffeld(Unit, WSS)
                    If Ziel.X >= 0 Then
                        If Objektverwalter.Spielfeld.AktuelleEinheit Is Nothing Then
                            Einheitauswaehlen(Unit, New Point(Unit.X, Unit.Y), KIModiExtern.Warten, Nothing, WSS)
                        Else
                            NaechsterBefehl(Ziel, Nothing, KIModiExtern.Warten, WSS, 4)
                        End If
                    Else
                        EinheitAbwaehlen()
                    End If
                Else
                    'Das ist mir die liebste und einfachst Situation Uff.
                    Dim Feld As Point = GetBestesFernkampfOpfer(Unit)
                    If Feld.X >= 0 Then
                        Einheitauswaehlen(Unit, New Point(Unit.X, Unit.Y), KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Feld.X, Feld.Y, Schlachtfeld), WSS, 4)
                    End If
                End If
            ElseIf Unit.MinimaleReichweite = 1 Or Not Unit.Waffe1 = "Keine" Then
                Dim WSS As Wegsuchsystem = CreateWSS(Unit)
                Dim Feld As Point2 = GetBestesNahkampfOpfer(Unit, WSS)
                If Feld.Point1.X >= 0 And Feld.Point2.X >= 0 Then
                    Einheitauswaehlen(Unit, Feld.Point1, KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Feld.Point2.X, Feld.Point2.Y, Schlachtfeld), WSS, 4)
                End If
            End If
            If Unit.HatsichBewegt = False Then
                'Nur ziehen ohne Angriff
                If Unit.MinimaleReichweite = 1 Or Not Unit.Waffe1 = "Keine" Then
                    'So das ist vieleicht eine Nahkampfeinheit und zwar kein Infaterist
                    'und diese Einheit kann nicht Angreifen oder doch nah ja das ist ja eine doofe KI
                    'Also keine Abfrage!
                    Dim WSS As New Wegsuchsystem(Unit, Unit.X, Unit.Y, Unit.GetMap, -1)
                    Dim Ziel As Point = GetNaehestenNahkampfFeind(Unit, WSS)
                    If Ziel.X >= 0 Then
                        Einheitauswaehlen(Unit, Ziel, KIModiExtern.Warten, Nothing, WSS, 4)
                    Else
                        Ziel = ZumNaehestenHQZiehen(Unit, WSS)
                        If Ziel.X > 0 Then
                            Einheitauswaehlen(Unit, Ziel, KIModiExtern.Warten, Nothing, WSS, 4)
                        End If
                    End If
                ElseIf Unit.MaximaleReichweite > 1 Then
                    Dim WSS As New Wegsuchsystem(Unit, Unit.X, Unit.Y, Unit.GetMap, -1)
                    Dim Ziel As Point = GetNaehestesFernkampffeld(Unit, WSS)
                    If Ziel.X >= 0 Then
                        Einheitauswaehlen(Unit, Ziel, KIModiExtern.Warten, Nothing, WSS, 4)
                    Else
                        Ziel = ZumNaehestenHQZiehen(Unit, WSS)
                        If Ziel.X > 0 Then
                            Einheitauswaehlen(Unit, Ziel, KIModiExtern.Warten, Nothing, WSS, 4)
                        End If
                    End If
                End If
            End If
            If Unit.HatsichBewegt = False Then 'Still didn't move simply Wait
                Einheitauswaehlen(Unit, Unit.GetLocation, KIModiExtern.Warten, Nothing, Nothing)
            End If
        End If
    End Sub
    ''' <summary>
    ''' Moves the Unit for Stop
    ''' </summary>
    ''' <param name="Unit"></param>
    ''' <remarks></remarks>
    Private Sub PredeployedMoveStop(ByVal Unit As ObjektEinheit)
        Dim Felder As New Stack(Of Point)
        Dim MaximaleReichweite As Integer = Unit.MaximaleReichweite
        Dim MinimaleReichweite As Integer = Unit.MinimaleReichweite
        Dim Kreis(,) As Integer = Kreisfunktion(MaximaleReichweite)
        For X1 = 0 To MaximaleReichweite * 2
            For Y1 = 0 To MaximaleReichweite * 2
                If Kreis(X1, Y1) >= MinimaleReichweite Then
                    Dim neuerPunkt As Point = New Point(Unit.X - MaximaleReichweite + X1, Unit.Y - MaximaleReichweite + Y1)
                    If Objektverwalter.Spielfeld.OnMap(neuerPunkt.X, neuerPunkt.Y) Then
                        If Sichtfeld(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld) = True Then
                            If Felder.Contains(neuerPunkt) = False Then
                                If Not Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld) Is Nothing Then
                                    If KannAngegriffenWerden(Unit, Objektverwalter.Spielfeld.Einheiten(neuerPunkt.X, neuerPunkt.Y, Schlachtfeld), True, New Point(Unit.X, Unit.Y)) = True Then
                                        Felder.Push(neuerPunkt)
                                    End If
                                End If
                            End If
                        End If
                    End If
                End If
            Next
        Next
        If Felder.Count > 0 Then
            Dim MomentanesOpfer As Integer = 0
            Dim MomentanerSchaden As Integer = 0
            For I = 0 To Felder.Count - 1
                Dim UnserOpfer As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(Felder(I).X, Felder(I).Y, Schlachtfeld)
                If Not UnserOpfer Is Nothing Then
                    Dim Glueck As Point = Spieler.GetGlueckPech(Unit.X, Unit.Y)
                    If Gluecksfaktor > 0 Then
                        Glueck.X *= Gluecksfaktor
                    Else
                        Glueck.X = Glueck.Y * Gluecksfaktor
                    End If
                    Dim OpferLeben As Single = UnserOpfer.Leben
                    Dim Schaden As Integer = UnserOpfer.Kosten * Objektverwalter.Spielfeld.Spieler(UnserOpfer.Spieler).Teurungsrate(UnserOpfer, UnserOpfer.X, UnserOpfer.Y) * Objektverwalter.Schadensberechnung(Unit, Unit.X, Unit.Y, UnserOpfer.X, UnserOpfer.Y, Unit.Leben, OpferLeben, False, True, Glueck.X, UnserOpfer, False)(0)
                    If Schaden > MomentanerSchaden Then
                        MomentanerSchaden = Schaden
                        MomentanesOpfer = I
                    ElseIf Schaden = MomentanerSchaden And Zufallszahl(0, 1) = 1 Then
                        MomentanerSchaden = Schaden
                        MomentanesOpfer = I
                    End If
                Else
                    'Wir greifen ein Gebaeude oder eine Landschaft an.
                    If Objektverwalter.Spielfeld.Landschaften(Felder(I).X, Felder(I).Y, Schlachtfeld).Leben > 0 Then
                        If MomentanerSchaden = 0 Then
                            If MomentanesOpfer <> 0 Then
                                If Zufallszahl(0, 1) = 0 Then
                                    MomentanesOpfer = I
                                End If
                            Else
                                MomentanesOpfer = I
                            End If
                        End If
                    Else
                        Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(Felder(I).X, Felder(I).Y, Schlachtfeld).Gebaeude
                        Dim Schaden As Integer = ObjektLadeklasse.GetGebaeudeKosten(G.GebaeudeID, G.Spieler) / G.GetMaxLeben * Tabellenverwalter.GetWert(Unit.Waffe2, "Gebaeude")
                        If Schaden > MomentanerSchaden Then
                            MomentanerSchaden = Schaden
                            MomentanesOpfer = I
                        ElseIf Schaden = MomentanerSchaden And Zufallszahl(0, 1) = 1 Then
                            MomentanerSchaden = Schaden
                            MomentanesOpfer = I
                        End If
                    End If
                End If
            Next
            If Felder(MomentanesOpfer).X >= 0 And Felder(MomentanesOpfer).Y >= 0 Then
                Einheitauswaehlen(Unit, Unit.GetLocation, KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Felder(MomentanesOpfer).X, Felder(MomentanesOpfer).Y, Schlachtfeld), Nothing)
            Else
                Einheitauswaehlen(Unit, Unit.GetLocation, KIModiExtern.Warten, Nothing, Nothing)
            End If
        Else
            Einheitauswaehlen(Unit, Unit.GetLocation, KIModiExtern.Warten, Nothing, Nothing)
        End If

    End Sub
    ''' <summary>
    ''' Waits until the Unit can Attack
    ''' </summary>
    ''' <param name="E"></param>
    ''' <remarks></remarks>
    Private Sub PredeployedMoveWaitForAttack(ByVal E As ObjektEinheit)
        If E.HatsichBewegt = False Then
            If E.Treibstoff > 0 Then
                If E.MaximaleReichweite > 1 Then
                    Dim WSS As Wegsuchsystem = CreateWSS(E)
                    'OH je  das wird noch komplikate
                    If Spieler.KOS(0).MoveandFire = True And Spieler.KOS(0).FireandMove = True Then
                        Dim Feld As Point = GetBestesFernkampfOpfer(E)
                        If Feld.X >= 0 Then
                            Einheitauswaehlen(E, New Point(E.X, E.Y), KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Feld.X, Feld.Y, Schlachtfeld), WSS)
                            Dim Felder As Point2 = GetBestesFernkampfFeldmitBewegung(E, WSS)
                            If Felder.Point1.X >= 0 And Felder.Point2.X >= 0 Then
                                'So wir haben ein Opfer.
                                NaechsterBefehl(Felder.Point1, Objektverwalter.Spielfeld.Einheiten(Felder.Point2.X, Felder.Point2.Y, Schlachtfeld), KIModiExtern.Angriff, WSS, 4)
                            End If
                        Else
                            Dim Felder As Point2 = GetBestesFernkampfFeldmitBewegung(E, WSS)
                            If Felder.Point1.X >= 0 And Felder.Point2.X >= 0 Then
                                'So wir haben ein Opfer.
                                Einheitauswaehlen(E, Felder.Point1, KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Felder.Point2.X, Felder.Point2.Y, Schlachtfeld), WSS)
                            End If
                        End If
                        EinheitAbwaehlen()
                    ElseIf Spieler.KOS(0).MoveandFire = True Then
                        'Ein Angriff ziehen und Feuern wie beim Nahkampf
                        Dim Felder As Point2 = GetBestesFernkampfFeldmitBewegung(E, WSS)
                        If Felder.Point1.X >= 0 And Felder.Point2.X >= 0 Then
                            'So wir haben ein Opfer.
                            Einheitauswaehlen(E, Felder.Point1, KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Felder.Point2.X, Felder.Point2.Y, Schlachtfeld), WSS)
                        End If
                    ElseIf Spieler.KOS(0).FireandMove = True Then
                        'Wir suchen uns ein Opfer
                        Dim Feld As Point = GetBestesFernkampfOpfer(E)
                        If Feld.X >= 0 Then
                            Einheitauswaehlen(E, New Point(E.X, E.Y), KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Feld.X, Feld.Y, Schlachtfeld), WSS)
                        End If
                        'wir haben unser Opfer angegriffen jetzt sollten wir die Einheit noch ziehen.
                        WSS = New Wegsuchsystem(E, E.X, E.Y, E.GetMap, -1)
                        Dim Ziel As Point = GetNaehestesFernkampffeld(E, WSS)
                        If Ziel.X >= 0 Then
                            If Objektverwalter.Spielfeld.AktuelleEinheit Is Nothing Then
                                Einheitauswaehlen(E, New Point(E.X, E.Y), KIModiExtern.Warten, Nothing, WSS)
                            Else
                                NaechsterBefehl(Ziel, Nothing, KIModiExtern.Warten, WSS, 4)
                            End If
                        Else
                            EinheitAbwaehlen()
                        End If
                    Else
                        'Das ist mir die liebste und einfachst Situation Uff.
                        Dim Feld As Point = GetBestesFernkampfOpfer(E)
                        If Feld.X >= 0 Then
                            Einheitauswaehlen(E, New Point(E.X, E.Y), KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Feld.X, Feld.Y, Schlachtfeld), WSS, 4)
                        End If
                    End If
                ElseIf E.MinimaleReichweite = 1 Or E.Waffe1 = "Keine" Then
                    'Wir lassen sie einen Nahkampf machen.
                    Dim WSS As Wegsuchsystem = CreateWSS(E)
                    Dim Feld As Point2 = GetBestesNahkampfOpfer(E, WSS)
                    If Feld.Point1.X >= 0 And Feld.Point2.X >= 0 Then
                        Einheitauswaehlen(E, Feld.Point1, KIModiExtern.Angriff, Objektverwalter.Spielfeld.Einheiten(Feld.Point2.X, Feld.Point2.Y, Schlachtfeld), WSS, 4)
                    End If
                End If
            End If
        End If
    End Sub
#End Region
End Class

''' <summary>
''' Diese Klasse haelt Funktionen fuer einen Intelligenten Bau einer Armee parat!
''' </summary>
''' <remarks></remarks>
Public NotInheritable Class KIGenerellerSuperBau
    ''' <summary>
    ''' Mit dieser Zahl werden Bauprioritaeten multipliziert!
    ''' </summary>
    ''' <remarks></remarks>
    Const InfantrieGewichtung As Integer = 10
    ''' <summary>
    ''' Wie gross ist eine kleine Karte
    ''' </summary>
    ''' <remarks></remarks>
    Const SmallMap As Integer = 225
    ''' <summary>
    ''' Wie gross ist eine Mittlere Karte
    ''' </summary>
    ''' <remarks></remarks>
    Const MediumMap As Integer = 600
    ''' <summary>
    ''' Minimales Einkommen fuer Bauaenderung
    ''' </summary>
    ''' <remarks></remarks>
    Const Einkommen As Integer = 12000
    ''' <summary>
    ''' Wie weit die naeheste Luftwaffe weg sein muss damit sich eine Missile lohnt!
    ''' </summary>
    ''' <remarks></remarks>
    Const LuftwaffenAbstand As Integer = 10
    ''' <summary>
    ''' Wenn wir soviel oder weniger verdienen lohnt sich sparen nicht!
    ''' </summary>
    ''' <remarks></remarks>
    Const MinimalesEinkommen As Integer = 4000
    Shared MinimaleInfiZahl As Integer = 5
    Shared NichtsGebaut As Boolean = True
    Shared AusgabeFonds As Integer = 0
    Shared BauModus As BauModi = BauModi.Infantrie
    Shared Gebaeude As ObjektGebaeude()
    Shared KI As ObjektKI
    Shared BauWichtigKeit As List(Of TruppenSorten)
    Public Class PrioritaetsBau
        Enum Prioritaeten
            Off
            Low
            Normal
            High
        End Enum
        Public Air As Prioritaeten
        Public Land As Prioritaeten
        Public Sea As Prioritaeten
        Public Direct As Prioritaeten
        Public Indirect As Prioritaeten
        Public Transport As Prioritaeten
        Public Infantrie As Prioritaeten
        Public DurchschnittlicheTruppenKosten As Integer
        Public Ausgabefonds As Integer
        Public AutoGenerated As Boolean
        Public Sub New(ByVal Air As Prioritaeten, ByVal Land As Prioritaeten, ByVal Sea As Prioritaeten, ByVal Direct As Prioritaeten, ByVal Indirect As Prioritaeten, ByVal Infantrie As Prioritaeten, ByVal Transport As Prioritaeten, ByVal DurchschnittlicheTruppenKosten As Integer, ByVal Ausgabefonds As Integer, Optional ByVal AutoGenerated As Boolean = False)
            Me.Air = Air
            Me.Land = Land
            Me.Sea = Sea
            Me.Direct = Direct
            Me.Indirect = Indirect
            Me.Infantrie = Infantrie
            Me.Transport = Transport
            Me.DurchschnittlicheTruppenKosten = DurchschnittlicheTruppenKosten
            If Me.DurchschnittlicheTruppenKosten <= 0 Then Me.DurchschnittlicheTruppenKosten = Einkommen
            Me.Ausgabefonds = Ausgabefonds
            If Me.Ausgabefonds <= 0 Then Me.Ausgabefonds = Einkommen
            Me.AutoGenerated = AutoGenerated
        End Sub
        ''' <summary>
        ''' Gibt die Werte wie bei der New Funktion als Integer mit | getrennt zurueck
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overrides Function ToString() As String
            Return CInt(Air).ToString + "|" + CInt(Land).ToString + "|" + CInt(Sea).ToString + "|" + CInt(Direct).ToString + "|" + CInt(Indirect).ToString + "|" + CInt(Infantrie).ToString + "|" + CInt(Transport).ToString + "|" + DurchschnittlicheTruppenKosten.ToString + "|" + Ausgabefonds.ToString
        End Function
        Public Sub Write(ByRef StrW As Filestream)
            StrW.WriteByte(Air)
            StrW.WriteByte(Land)
            StrW.WriteByte(Sea)
            StrW.WriteByte(Direct)
            StrW.WriteByte(Indirect)
            StrW.WriteByte(Transport)
            StrW.WriteByte(Infantrie)
            Dim B(3) As Byte
            B = IntToBytes(DurchschnittlicheTruppenKosten)
            For I = 0 To B.Length - 1
                StrW.WriteByte(B(I))
            Next
            B = IntToBytes(Ausgabefonds)
            For I = 0 To B.Length - 1
                StrW.WriteByte(B(I))
            Next
            StrW.WriteByte(AutoGenerated)
        End Sub
        Public Sub Read(ByRef StrR As Filestream)
            Air = StrR.ReadByte
            Land = StrR.ReadByte
            Sea = StrR.ReadByte
            Direct = StrR.ReadByte
            Indirect = StrR.ReadByte
            Transport = StrR.ReadByte
            Infantrie = StrR.ReadByte
            Dim B(3) As Byte
            For I = 0 To B.Length - 1
                B(I) = StrR.ReadByte
            Next
            DurchschnittlicheTruppenKosten = BytesToInt(B)
            For I = 0 To B.Length - 1
                B(I) = StrR.ReadByte
            Next
            Ausgabefonds = BytesToInt(B)
            AutoGenerated = StrR.ReadByte
        End Sub
        Public Function IsClear() As Boolean
            If Air = Prioritaeten.Off Then
                If Land = Prioritaeten.Off Then
                    If Sea = Prioritaeten.Off Then
                        If Direct = Prioritaeten.Off Then
                            If Indirect = Prioritaeten.Off Then
                                If Transport = Prioritaeten.Off Then
                                    If Infantrie = Prioritaeten.Off Then
                                        If DurchschnittlicheTruppenKosten = 0 Then
                                            If Ausgabefonds = 0 Then
                                                If AutoGenerated = False Then
                                                    Return True
                                                End If
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    End If
                End If
            End If
            Return False
        End Function
    End Class
    ''' <summary>
    ''' Die einzelnen Bau Module zur Frage bei welchem wir sind!
    ''' </summary>
    ''' <remarks></remarks>
    Enum BauModi
        ''' <summary>
        ''' Wir stellen Infis her!
        ''' </summary>
        ''' <remarks></remarks>
        Infantrie
        ''' <summary>
        ''' Wir bauen Waffen gegen die Lufwaffe!
        ''' </summary>
        ''' <remarks></remarks>
        AntiAirUnits
        ''' <summary>
        ''' Stellt TTP's und T-Helis her!
        ''' </summary>
        ''' <remarks></remarks>
        TransporterBauInfis
        ''' <summary>
        ''' Mal sehen ob wir Transporter bauen!
        ''' </summary>
        ''' <remarks></remarks>
        TransporterBau
    End Enum
    Enum TruppenSorten
        Air
        Ground
        Sea
    End Enum

    Shared BauPrioritaeten As PrioritaetsBau
    ''' <summary>
    ''' Die einzige Moeglichkeit diese Klasse anzusprechen.
    ''' Startet einen sofortigen Bau-Zug einer KI!
    ''' Hinweis: Objektverwalter.Spielfeld.CurrentAI darf nicht nichts sein!
    ''' </summary>
    ''' <param name="Gebaeude1"></param>
    ''' <remarks></remarks>
    Public Shared Sub Bauen(ByVal Gebaeude1 As ObjektGebaeude(), ByVal Prioritaeten As PrioritaetsBau)
        'Shared Variablen setzen.
        AusgabeFonds = 0
        BauModus = BauModi.Infantrie
        NichtsGebaut = True
        KI = Objektverwalter.Spielfeld.CurrentAI
        BauPrioritaeten = Prioritaeten
        Gebaeude = Gebaeude1
        GenerateBauWichtigkeit()
        'Neutral oder Alles
        Dim AllBuildings As Integer = Objektverwalter.Spielfeld.CountBuildings
        'Gebaeude feindlichen
        Dim EnemyBuildings As Integer = CountEnemyBuildings()
        Dim EnemyBuildingProzent As Integer = ProzentualeGebaeudeVerteilung() - BauPrioritaeten.Infantrie * InfantrieGewichtung
        Dim NeutralBuildings As Integer = CountNeutralBuildings()
        'Eigene Gebaeude
        Dim OwnBases As Integer = CountOwnBases()
        Dim OwnAirports As Integer = CountOwnAirports()
        Dim OwnPorts As Integer = CountOwnPorts()
        'Einheiten Feindliche
        Dim EnemyAirUnits As Integer = CountEnemyAirUnits()
        Dim IndirectEnemyUnits As Integer = CountIndirectEnemys()
        Dim DirectEnemyUnits As Integer = CountDirectEnemys()
        Dim EnemyGroundUnits As Integer = CountEnemyGroundUnits()
        Dim EnemySeaForce As Integer = CountEnemySeaUnits()
        Dim EnemyUnits As Integer = CountEnemyUnits()
        Dim EnemyCopters As Integer = CountEnemyCopters()
        Dim EnemyAntiAirUnits As Integer = CountEnemyAntiAirUnits()
        'Einheiten Eigene
        Dim AntiAirUnits As Integer = CountAntiAirUnits()
        Dim OwnGroundUnits As Integer = CountGroundUnits()
        Dim OwnSeaUnits As Integer = CountSeaUnits()
        Dim OwnAirUnits As Integer = CountAirUnits()
        Dim Infis As Integer = CountInfanteristen()
        Dim OwnUnits As Integer = CountOwnUnits()
        Dim OwnLanders As Integer = CountAnyUnit("L-BOOT")
        Dim OwnTransportplanes As Integer = CountAnyUnit("T-FLUGZEUG")
        Dim OwnTTPs As Integer = CountAnyUnit("TTP")
        Dim OwnTHelis As Integer = CountAnyUnit("T-HELI")
        Dim OwnIndirectUnits As Integer = CountIndirectUnits()
        Dim OwnDirectUnits As Integer = CountDirectUnits()
        'Noch andere Sachen
        Dim LBootBau As Boolean = IsTransporterBauSinnvoll(Gebaeude) 'Landeboote
        Dim MapSize As Integer = Objektverwalter.Spielfeld.GetSpielgroesse
        Dim RationTroops As Integer = GetNeededRation()
        'Wenn das False wird dann schauen wir weiter und weiter und weiter.=D

        Dim Income As Integer = Objektverwalter.Spielfeld.CurrentAI.Spieler.Einkommen
        Dim FondsNaechsteRunde As Integer = Objektverwalter.Spielfeld.CurrentAI.Spieler.Fonds
        FondsNaechsteRunde += Income - Objektverwalter.Spielfeld.CurrentAI.Spieler.GetRepairCosts
        If Objektverwalter.Spielfeld.Runde > 1 Then
            If BauPrioritaeten.Ausgabefonds < KI.Spieler.Fonds Then
                AusgabeFonds = KI.Spieler.Fonds 'Wir duerfen alles ausgeben. Haehae!
            Else
                If Income <= MinimalesEinkommen Then
                    AusgabeFonds = KI.Spieler.Fonds 'Wir duerfen alles ausgeben. Haehae!
                ElseIf Income * 2 <= BauPrioritaeten.Ausgabefonds Then
                    AusgabeFonds = KI.Spieler.Fonds
                Else
                    'da muss mir wohl etwas Sparsamer sein!
                    AusgabeFonds = FondsNaechsteRunde - BauPrioritaeten.DurchschnittlicheTruppenKosten
                End If
            End If
        Else
            AusgabeFonds = KI.Spieler.Fonds
        End If


        'So und jetzt noch ein paar Shared Sachen festlegen
        'Minimale Infanteristen Zahl berechnen!
        Select Case BauPrioritaeten.Infantrie
            Case PrioritaetsBau.Prioritaeten.Off
                MinimaleInfiZahl = 1
            Case PrioritaetsBau.Prioritaeten.Low
                MinimaleInfiZahl = 3
            Case PrioritaetsBau.Prioritaeten.Normal
                MinimaleInfiZahl = 5
            Case PrioritaetsBau.Prioritaeten.High
                MinimaleInfiZahl = 7
        End Select
        If NeutralBuildings / AllBuildings < 10 Or EnemyBuildingProzent < 100 Then
            MinimaleInfiZahl -= (3 - BauPrioritaeten.Infantrie)
            If Income > Einkommen Then
                MinimaleInfiZahl -= (3 - BauPrioritaeten.Infantrie)
            End If
            If MinimaleInfiZahl <= 0 Then MinimaleInfiZahl = 1
        End If

        Gebaeude = TrimGebaeude(Gebaeude)
        Gebaeude = SortGebaeude(Gebaeude, KI.Spieler)

        Dim MomentaneEinheit As Integer = 0
        If KI.Spieler.VeraenderteWerte.KeinBau = False Then
            While MomentaneEinheit < Gebaeude.Length
Start:
                NichtsGebaut = True
                'unser erste Aufgabe sollte darin bestehen zu schauen ob wir Infanteristen brauchen!
                If BauModus <= BauModi.Infantrie Then
                    If EnemyBuildingProzent < 100 And Infis <= MinimaleInfiZahl Then
                        If BauPlanAenderung(InfisBauen(AusgabeFonds), Infis) Then GoTo Start
                    ElseIf Infis < MinimaleInfiZahl Then 'Das spricht fuer eine Infiflut
                        If BauPlanAenderung(InfisBauen(AusgabeFonds), Infis) Then GoTo Start
                    ElseIf BauPrioritaeten.Infantrie = PrioritaetsBau.Prioritaeten.High Then
                        If MapSize < MediumMap And Infis / OwnUnits < 50 Then '50% sollten dann woll Infis sein!
                            If BauPlanAenderung(InfisBauen(AusgabeFonds), Infis) Then GoTo Start
                        End If
                    End If
                End If
                'Wir bauen Truppen gegen die Luftwaffe
                If BauModus <= BauModi.AntiAirUnits Then
                    If AntiAirBau(AntiAirUnits, EnemyAirUnits) Then
                        If BauPlanAenderung(ProduceAntiAirUnit(EnemyAntiAirUnits, AusgabeFonds), AntiAirUnits) Then GoTo Start
                    End If
                End If
                'Jetzt Truppentransporter!
                If BauModus <= BauModi.TransporterBauInfis Then
                    Select Case BauPrioritaeten.Transport
                        Case PrioritaetsBau.Prioritaeten.Low
                            If Objektverwalter.Spielfeld.Runde < 5 And EnemyBuildingProzent > 120 Then
                                If OwnTTPs + OwnTHelis <= 0 Then
                                    If Zufallszahl(1, 100) <= 50 Then
                                        If BauPlanAenderung(ProduceUnit("TTP", AusgabeFonds), OwnTTPs) Then GoTo Start
                                    Else
                                        If BauPlanAenderung(ProduceUnit("T-HELI", AusgabeFonds), OwnTHelis) Then GoTo Start
                                    End If
                                End If
                            End If
                        Case PrioritaetsBau.Prioritaeten.Normal
                            If MapSize < SmallMap Then
                                If Objektverwalter.Spielfeld.Runde > 5 And EnemyBuildingProzent > 100 Then
                                    If OwnTTPs < 1 Then
                                        If BauPlanAenderung(ProduceUnit("TTP", AusgabeFonds), OwnTTPs) Then GoTo Start
                                    End If
                                End If
                            ElseIf Objektverwalter.Spielfeld.Runde < 6 Or EnemyBuildingProzent > 100 Or RationTroops > 3 Then
                                If MapSize < MediumMap Then
                                    If OwnTTPs < 1 Then
                                        If BauPlanAenderung(ProduceUnit("TTP", AusgabeFonds), OwnTTPs) Then GoTo Start
                                    ElseIf OwnTHelis < 1 Then
                                        If BauPlanAenderung(ProduceUnit("T-HELI", AusgabeFonds), OwnTHelis) Then GoTo Start
                                    End If
                                Else
                                    If OwnTTPs < 2 Then
                                        If BauPlanAenderung(ProduceUnit("TTP", AusgabeFonds), OwnTTPs) Then GoTo Start
                                    ElseIf OwnTHelis < 1 Then
                                        If BauPlanAenderung(ProduceUnit("T-HELI", AusgabeFonds), OwnTHelis) Then GoTo Start
                                    End If
                                End If
                            End If
                        Case PrioritaetsBau.Prioritaeten.High
                            If MapSize < SmallMap Then
                                If OwnTTPs < 1 Then
                                    If BauPlanAenderung(ProduceUnit("TTP", AusgabeFonds), OwnTTPs) Then GoTo Start
                                End If
                            ElseIf MapSize < MediumMap Then
                                If OwnTTPs < 1 Then
                                    If BauPlanAenderung(ProduceUnit("TTP", AusgabeFonds), OwnTTPs) Then GoTo Start
                                ElseIf OwnTHelis < 1 Then
                                    If BauPlanAenderung(ProduceUnit("T-HELI", AusgabeFonds), OwnTHelis) Then GoTo Start
                                End If
                            Else
                                If RationTroops > 3 And OwnTTPs < 2 Then
                                    If BauPlanAenderung(ProduceUnit("TTP", AusgabeFonds), OwnTTPs) Then GoTo Start
                                Else
                                    If Objektverwalter.Spielfeld.Runde < 6 Or EnemyBuildingProzent > 100 Then
                                        If OwnTTPs < 2 Then
                                            If BauPlanAenderung(ProduceUnit("TTP", AusgabeFonds), OwnTTPs) Then GoTo Start
                                        ElseIf OwnTHelis < 2 Then
                                            If BauPlanAenderung(ProduceUnit("T-HELI", AusgabeFonds), OwnTHelis) Then GoTo Start
                                        End If
                                    End If
                                End If
                            End If
                        Case PrioritaetsBau.Prioritaeten.Off 'Also keine TTPs und T-Heli's
                    End Select
                End If
                'So jetzt kuemmern wir uns um die Transporter!
                If BauModus <= BauModi.TransporterBau Then
                    If LBootBau Then
                        'Also wir haben auch Truppen zum transportieren!
                        If BauPrioritaeten.Sea < BauPrioritaeten.Air Then
                            'Wir bauen mehr T-Flugzeuge als L-Boote
                            Select Case BauPrioritaeten.Transport
                                Case PrioritaetsBau.Prioritaeten.Low 'Eins muss reichen!
                                    If OwnTransportplanes + OwnLanders < 1 Then
                                        If BauPlanAenderung(ProduceUnitOrUnit("T-Flugzeug", "L-BOOT", AusgabeFonds), OwnTransportplanes) Then GoTo Start
                                    End If
                                Case PrioritaetsBau.Prioritaeten.Normal
                                    If OwnTransportplanes + OwnLanders < 2 Then
                                        If BauPlanAenderung(ProduceUnitOrUnit("T-Flugzeug", "L-BOOT", AusgabeFonds), OwnTransportplanes) Then GoTo Start
                                    End If
                                Case PrioritaetsBau.Prioritaeten.High
                                    If OwnTransportplanes + OwnLanders < 4 Then
                                        If BauPlanAenderung(ProduceUnitOrUnit("T-Flugzeug", "L-BOOT", AusgabeFonds), OwnTransportplanes) Then GoTo Start
                                    End If
                                Case Else 'Keine Transporter! :(
                            End Select
                        Else
                            'Wir bauen mehr L-Boote als T-Flugzeuge
                            Select Case BauPrioritaeten.Transport
                                Case PrioritaetsBau.Prioritaeten.Low 'Eins muss reichen!
                                    If OwnTransportplanes + OwnLanders < 1 Then
                                        If BauPlanAenderung(ProduceUnitOrUnit("L-BOOT", "T-Flugzeug", AusgabeFonds), OwnTransportplanes) Then GoTo Start
                                    End If
                                Case PrioritaetsBau.Prioritaeten.Normal
                                    If OwnTransportplanes + OwnLanders < 2 Then
                                        If BauPlanAenderung(ProduceUnitOrUnit("L-BOOT", "T-Flugzeug", AusgabeFonds), OwnTransportplanes) Then GoTo Start
                                    End If
                                Case PrioritaetsBau.Prioritaeten.High
                                    If OwnTransportplanes + OwnLanders < 4 Then
                                        If BauPlanAenderung(ProduceUnitOrUnit("L-BOOT", "T-Flugzeug", AusgabeFonds), OwnTransportplanes) Then GoTo Start
                                    End If
                                Case Else 'Keine Transporter! :(
                            End Select
                        End If
                    End If
                End If
                'So jetzt bauen wir die beste Einheit!
                BauPlanAenderung(ProduceBestUnit(AusgabeFonds, OwnAirUnits, OwnGroundUnits, OwnSeaUnits, OwnUnits, EnemyAntiAirUnits, OwnDirectUnits, OwnIndirectUnits), 0)

                'Haben wir etwas Gebaut?
                If NichtsGebaut Then
                    MomentaneEinheit = Gebaeude.Length + 1 'Damit waeren wir dann wohl fertig, wenn es einmal schief geht geht es auch 2 mal schief!
                Else
                    BauModus = BauModi.Infantrie
                    'Weiter Geht es!
                    MomentaneEinheit = 0
                End If
            End While
        End If




        'Alles loeschen
        KI = Nothing
        BauPrioritaeten = Nothing
        Gebaeude = Nothing
    End Sub

#Region "Truppen Bau"
    Private Shared Function BauPlanAenderung(ByVal Ausgabe As Integer, ByRef TruppenErhoehung As Integer) As Boolean
        AusgabeFonds -= Ausgabe
        If Ausgabe > 0 Then
            TruppenErhoehung += 1
            NichtsGebaut = False
            BauModus = BauModi.Infantrie
        End If
        If NichtsGebaut Then
            BauModus += 1
        End If
        Return Not NichtsGebaut
    End Function
    ''' <summary>
    ''' Stellt einen Infatristen her!
    ''' </summary>
    ''' <param name="Prueffonds"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function InfisBauen(ByRef Prueffonds As Integer) As Integer
        Dim Ausgabe As Integer = 0
        If Prueffonds < 0 Then
            Prueffonds = KI.Spieler.Fonds
        End If
        Dim MinRunde As Integer = BauPrioritaeten.Infantrie + 1
        For I = 0 To Gebaeude.Length - 1
            If IsFeldLeer(Gebaeude(I).Rechteck.X, Gebaeude(I).Rechteck.Y) Then
                Dim Infis As String() = GetBuildInfis(Gebaeude(I), Prueffonds)
                If Infis.Length > 0 Then
                    If ObjektKI.CanMoveAfterBuilding(New EinheitInfanterie(0, 0, 0), Gebaeude(I).Rechteck.X, Gebaeude(I).Rechteck.Y) = True Then
                        If Objektverwalter.Spielfeld.Runde <= MinRunde Or Zufallszahl(1, 100) < 70 Then
                            Dim BilligsteTruppe As ObjektEinheit = Nothing
                            For I2 = 0 To Infis.Length - 1
                                Dim E As ObjektEinheit = ObjektLadeklasse.NewEinheit(Infis(I2), KI.Spieler.Spieler, Gebaeude(I).Rechteck.X, Gebaeude(I).Rechteck.Y)
                                If BilligsteTruppe Is Nothing Then
                                    BilligsteTruppe = E
                                ElseIf E.Kosten < BilligsteTruppe.Kosten Then
                                    BilligsteTruppe = E
                                ElseIf E.Kosten = BilligsteTruppe.Kosten And Zufallszahl(0, 2) = 0 Then
                                    BilligsteTruppe = E
                                End If
                            Next
                            'Dann mal los ihr Infis
                            Ausgabe = BilligsteTruppe.Kosten * KI.Spieler.Teurungsrate(BilligsteTruppe, BilligsteTruppe.X, BilligsteTruppe.Y)
                            ProduceUnit(Gebaeude(I), BilligsteTruppe)
                            Return Ausgabe
                        Else
                            Dim E As ObjektEinheit = ObjektLadeklasse.NewEinheit(Infis(Zufallszahl(0, Infis.Length - 1)), KI.Spieler.Spieler, Gebaeude(I).Rechteck.X, Gebaeude(I).Rechteck.Y)
                            Ausgabe = E.Kosten * KI.Spieler.Teurungsrate(E, E.X, E.Y)
                            ProduceUnit(Gebaeude(I), E)
                            Return Ausgabe
                        End If
                    End If
                End If
            End If
        Next
        Return Ausgabe
    End Function
    ''' <summary>
    ''' Stellt eine ganz bestimmte Einheit her.
    ''' </summary>
    ''' <param name="Unit">Die EinheitenID die wir bauen wollen!</param>
    ''' <param name="Prueffonds">Wie teuer die Einheit sein darf!</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function ProduceUnit(ByVal Unit As String, ByVal Prueffonds As Integer) As Integer
        Dim Ausgabe As Integer = 0
        If Prueffonds < 0 Then
            Prueffonds = KI.Spieler.Fonds
        End If
        For I = 0 To Gebaeude.Length - 1
            If IsFeldLeer(Gebaeude(I).Rechteck.X, Gebaeude(I).Rechteck.Y) Then 'Wir wollen ja was bauen!
                If Gebaeude(I).CanBuildUnit(Unit, Prueffonds) Then
                    Dim E As ObjektEinheit = ObjektLadeklasse.NewEinheit(Unit, KI.Spieler.Spieler, Gebaeude(I).Rechteck.X, Gebaeude(I).Rechteck.Y)
                    If ObjektKI.CanMoveAfterBuilding(E, E.X, E.Y) Then
                        Ausgabe = E.Kosten * KI.Spieler.Teurungsrate(E, E.X, E.Y)
                        ProduceUnit(Gebaeude(I), E)
                        Return Ausgabe
                    End If
                End If
            End If
        Next
        Return Ausgabe
    End Function
    ''' <summary>
    ''' Stellt eine ganz bestimmte Einheit her oder die andere.
    ''' </summary>
    ''' <param name="Unit1">Die EinheitenID die wir bauen wollen!</param>
    ''' <param name="Prueffonds">Wie teuer die Einheit sein darf!</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function ProduceUnitOrUnit(ByVal Unit1 As String, ByVal Unit2 As String, ByVal Prueffonds As Integer) As Integer
        Dim Ausgabe As Integer = 0
        If Prueffonds < 0 Then
            Prueffonds = KI.Spieler.Fonds
        End If
        For I = 0 To Gebaeude.Length - 1
            If IsFeldLeer(Gebaeude(I).Rechteck.X, Gebaeude(I).Rechteck.Y) Then 'Wir wollen ja was bauen!
                If Gebaeude(I).CanBuildUnit(Unit1, Prueffonds) Then
                    Dim E As ObjektEinheit = ObjektLadeklasse.NewEinheit(Unit1, KI.Spieler.Spieler, Gebaeude(I).Rechteck.X, Gebaeude(I).Rechteck.Y)
                    If ObjektKI.CanMoveAfterBuilding(E, E.X, E.Y) Then
                        Ausgabe = E.Kosten * KI.Spieler.Teurungsrate(E, E.X, E.Y)
                        ProduceUnit(Gebaeude(I), E)
                        Return Ausgabe
                    End If
                End If
            End If
        Next
        For I = 0 To Gebaeude.Length - 1
            If IsFeldLeer(Gebaeude(I).Rechteck.X, Gebaeude(I).Rechteck.Y) Then 'Wir wollen ja was bauen!
                If Gebaeude(I).CanBuildUnit(Unit2, Prueffonds) Then
                    Dim E As ObjektEinheit = ObjektLadeklasse.NewEinheit(Unit2, KI.Spieler.Spieler, Gebaeude(I).Rechteck.X, Gebaeude(I).Rechteck.Y)
                    If ObjektKI.CanMoveAfterBuilding(E, E.X, E.Y) Then
                        Ausgabe = E.Kosten * KI.Spieler.Teurungsrate(E, E.X, E.Y)
                        ProduceUnit(Gebaeude(I), E)
                        Return Ausgabe
                    End If
                End If
            End If
        Next
        Return Ausgabe
    End Function
    ''' <summary>
    ''' Baut eine Einheit gegen die Luftwaffe!
    ''' </summary>
    ''' <param name="EnemyAntiAirUnits"></param>
    ''' <param name="Prueffonds"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function ProduceAntiAirUnit(ByVal EnemyAntiAirUnits As Integer, ByVal Prueffonds As Integer) As Integer
        Dim Geb As ObjektGebaeude = Nothing
        Dim Distance As Integer = -1
        Dim Bauliste As ObjektEinheit() = Nothing
        For I = 0 To BauWichtigKeit.Count - 1
            Select Case BauWichtigKeit(I)
                Case TruppenSorten.Ground 'Schauen wir mal was wir bauen sollten!
                    For Each G In Gebaeude
                        If IsFeldLeer(G.Rechteck.X, G.Rechteck.Y) Then
                            Dim GB As ObjektEinheit() = G.GetGroundUnits(Prueffonds)
                            If GB.Length > 0 Then
                                Dim E As Integer = GetAirDistance(G, TruppenSorten.Ground)
                                If E < Distance Or Distance < 0 Then
                                    Geb = G
                                    Distance = E
                                    Bauliste = GB
                                End If
                            End If
                        End If
                    Next
                    If Distance >= 0 And Zufallszahl(1, 100) < 75 Then
                        GoTo ProduceUnit
                    End If
                Case TruppenSorten.Air
                    For Each G In Gebaeude
                        If IsFeldLeer(G.Rechteck.X, G.Rechteck.Y) Then
                            Dim GB As ObjektEinheit() = G.GetAirUnits(Prueffonds)
                            If GB.Length > 0 Then
                                Dim E As Integer = GetAirDistance(G, TruppenSorten.Air)
                                If E < Distance Or Distance < 0 Then
                                    Geb = G
                                    Distance = E
                                    Bauliste = GB
                                End If
                            End If
                        End If
                    Next
                    If Distance >= 0 And Zufallszahl(1, 100) < 75 Then
                        GoTo ProduceUnit
                    End If
                Case TruppenSorten.Sea
                    For Each G In Gebaeude
                        If IsFeldLeer(G.Rechteck.X, G.Rechteck.Y) Then
                            Dim GB As ObjektEinheit() = G.GetSeaUnits(Prueffonds)
                            If GB.Length > 0 Then
                                Dim E As Integer = GetAirDistance(G, TruppenSorten.Sea)
                                If E < Distance Or Distance < 0 Then
                                    Geb = G
                                    Distance = E
                                    Bauliste = GB
                                End If
                            End If
                        End If
                    Next
                    If Distance >= 0 And Zufallszahl(1, 100) < 75 Then
                        GoTo ProduceUnit
                    End If
            End Select
        Next
ProduceUnit:
        Dim Ausgabe As Integer = 0
        If Bauliste IsNot Nothing Then
            Dim Beste As Integer = -1
            Dim Staerke As Integer = -1
            For I = 0 To Bauliste.Length - 1
                If ObjektKI.CanMoveAfterBuilding(Bauliste(I), Geb.Rechteck.X, Geb.Rechteck.Y) Then
                    If Bauliste(I).MinimaleReichweite > 1 And Distance <= LuftwaffenAbstand Then
                        'Jetzt eine Fernwaffe waere sehr schlecht
                    Else
                        Dim NeuStaerke As Integer = GetAntiAirDamage(Bauliste(I)) / (Bauliste(I).Kosten * KI.Spieler.Teurungsrate(Bauliste(I), Bauliste(I).X, Bauliste(I).Y))
                        If NeuStaerke > Staerke Then
                            Staerke = NeuStaerke
                            Beste = I
                        ElseIf NeuStaerke = Staerke And Zufallszahl(0, 2) = 0 Then
                            Staerke = NeuStaerke
                            Beste = I
                        End If
                    End If
                End If
            Next
            If Beste >= 0 Then
                Ausgabe = Bauliste(Beste).Kosten * KI.Spieler.Teurungsrate(Bauliste(Beste), Bauliste(Beste).X, Bauliste(Beste).Y)
                ProduceUnit(Geb, Bauliste(Beste))
                Return Ausgabe
            End If
        End If
        Return Ausgabe
    End Function
    ''' <summary>
    ''' Baut eine Einheit
    ''' </summary>
    ''' <remarks></remarks>
    Private Shared Sub ProduceUnit(ByVal G As ObjektGebaeude, ByVal E As ObjektEinheit)
        Dim M As ObjektSpielMenue = Objektverwalter.Menue
        If Not M.Spielmodus = ObjektSpielMenue.Spielmodi.KOSprechen Then
            M.Spielmodus = ObjektSpielMenue.Spielmodi.Nichts
        End If
        KI.KIZieht = True
        KI.KIWarteFrames = 4
        Try
            Threading.Thread.Sleep(System.Threading.Timeout.Infinite)
        Catch
        End Try
        Objektverwalter.EinheitBauen(New String() {E.EinheitenID, E.Kosten * KI.Spieler.Teurungsrate(E, G.Rechteck.X, G.Rechteck.Y)}, G.Rechteck.X, G.Rechteck.Y, True, True)
        Objektverwalter.ZuFeldgehen(E.X, E.Y)
    End Sub
    ''' <summary>
    ''' Baut die Beste Einheit fuer diese Runde!
    ''' </summary>
    ''' <param name="Prueffonds"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function ProduceBestUnit(ByVal Prueffonds As Integer, ByVal OwnAirUnits As Integer, ByVal OwnGroundUnits As Integer, ByVal OwnSeaUnits As Integer, ByVal OwnUnits As Integer, ByVal EnemyAntiAirUnits As Integer, ByVal OwnDirectUnits As Integer, ByVal OwnIndirectUnits As Integer) As Integer
        Dim Ausgabe As Integer = 0
        Dim Geb As ObjektGebaeude = Nothing
        Dim Bauliste As ObjektEinheit() = Nothing
        Dim GesamtPrioritaet As Integer = BauPrioritaeten.Land + BauPrioritaeten.Sea + BauPrioritaeten.Air
        For I = 0 To BauWichtigKeit.Count - 1
            Select Case BauWichtigKeit(I)
                Case TruppenSorten.Air
                    If BauPrioritaeten.Air > PrioritaetsBau.Prioritaeten.Off Then
                        'Wie viel Prozent sind Luftwaffe
                        Dim AirProzent As Integer = 0
                        If OwnUnits > 0 Then AirProzent = (OwnAirUnits) / OwnUnits * 100
                        'Wie viel sollten es sein
                        Dim AirProzReal As Integer = BauPrioritaeten.Air / GesamtPrioritaet * 100
                        If AirProzent <= AirProzReal Then 'Wir wollen eine Lufteinheit herstellen?
                            'Ist es sinnvoll Lufteinheiten zu bauen?
                            If EnemyAntiAirUnits - OwnGroundUnits / 2 - OwnSeaUnits / 2 - OwnAirUnits / 4 <= 0 Then
                                For Each G In Gebaeude
                                    If IsFeldLeer(G.Rechteck.X, G.Rechteck.Y) Then
                                        Dim GB As ObjektEinheit() = G.GetAirUnits(Prueffonds)
                                        If GB.Length > 0 Then
                                            If Bauliste IsNot Nothing Then
                                                If Bauliste.Length > GB.Length Then
                                                    Geb = G
                                                    Bauliste = GB
                                                End If
                                            Else
                                                Geb = G
                                                Bauliste = GB
                                            End If
                                        End If
                                    End If
                                Next
                            ElseIf BauPrioritaeten.Air = PrioritaetsBau.Prioritaeten.High And EnemyAntiAirUnits / OwnAirUnits <= 1 And Zufallszahl(1, 100) < 40 Then
                                For Each G In Gebaeude
                                    If IsFeldLeer(G.Rechteck.X, G.Rechteck.Y) Then
                                        Dim GB As ObjektEinheit() = G.GetAirUnits(Prueffonds)
                                        If GB.Length > 0 Then
                                            If Bauliste IsNot Nothing Then
                                                If Bauliste.Length > GB.Length Then
                                                    Geb = G
                                                    Bauliste = GB
                                                End If
                                            Else
                                                Geb = G
                                                Bauliste = GB
                                            End If
                                        End If
                                    End If
                                Next
                            End If
                        End If
                    End If
                Case TruppenSorten.Ground
                    If BauPrioritaeten.Land > PrioritaetsBau.Prioritaeten.Off Then
                        'Wie viel Prozent sind Luftwaffe
                        Dim AirProzent As Integer = 0
                        If OwnUnits > 0 Then AirProzent = (OwnGroundUnits) / OwnUnits * 100
                        'Wie viel sollten es sein
                        Dim AirProzReal As Integer = BauPrioritaeten.Land / GesamtPrioritaet * 100
                        If AirProzent <= AirProzReal Then 'Wir wollen eine Lufteinheit herstellen?
                            'Ist es sinnvoll Lufteinheiten zu bauen?
                            For Each G In Gebaeude
                                If IsFeldLeer(G.Rechteck.X, G.Rechteck.Y) Then
                                    Dim GB As ObjektEinheit() = G.GetGroundUnits(Prueffonds)
                                    If GB.Length > 0 Then
                                        If Bauliste IsNot Nothing Then
                                            If Bauliste.Length > GB.Length Then
                                                Geb = G
                                                Bauliste = GB
                                            End If
                                        Else
                                            Geb = G
                                            Bauliste = GB
                                        End If
                                    End If
                                End If
                            Next
                        ElseIf BauPrioritaeten.Land = PrioritaetsBau.Prioritaeten.High And Zufallszahl(1, 100) < 40 Then
                            For Each G In Gebaeude
                                If IsFeldLeer(G.Rechteck.X, G.Rechteck.Y) Then
                                    Dim GB As ObjektEinheit() = G.GetGroundUnits(Prueffonds)
                                    If GB.Length > 0 Then
                                        If Bauliste IsNot Nothing Then
                                            If Bauliste.Length > GB.Length Then
                                                Geb = G
                                                Bauliste = GB
                                            End If
                                        Else
                                            Geb = G
                                            Bauliste = GB
                                        End If
                                    End If
                                End If
                            Next
                        End If
                    End If
                Case TruppenSorten.Sea
                    If BauPrioritaeten.Sea > PrioritaetsBau.Prioritaeten.Off Then
                        'Wie viel Prozent sind Luftwaffe
                        Dim AirProzent As Integer = 0
                        If OwnUnits > 0 Then AirProzent = (OwnSeaUnits) / OwnUnits * 100
                        'Wie viel sollten es sein
                        Dim AirProzReal As Integer = BauPrioritaeten.Sea / GesamtPrioritaet * 100
                        If AirProzent <= AirProzReal Then 'Wir wollen eine Lufteinheit herstellen?
                            'Ist es sinnvoll Lufteinheiten zu bauen?
                            For Each G In Gebaeude
                                If IsFeldLeer(G.Rechteck.X, G.Rechteck.Y) Then
                                    Dim GB As ObjektEinheit() = G.GetSeaUnits(Prueffonds)
                                    If GB.Length > 0 Then
                                        If Bauliste IsNot Nothing Then
                                            If Bauliste.Length > GB.Length Then
                                                Geb = G
                                                Bauliste = GB
                                            End If
                                        Else
                                            Geb = G
                                            Bauliste = GB
                                        End If
                                    End If
                                End If
                            Next
                        ElseIf BauPrioritaeten.Sea = PrioritaetsBau.Prioritaeten.High And Zufallszahl(1, 100) < 40 Then
                            For Each G In Gebaeude
                                If IsFeldLeer(G.Rechteck.X, G.Rechteck.Y) Then
                                    Dim GB As ObjektEinheit() = G.GetSeaUnits(Prueffonds)
                                    If GB.Length > 0 Then
                                        If Bauliste IsNot Nothing Then
                                            If Bauliste.Length > GB.Length Then
                                                Geb = G
                                                Bauliste = GB
                                            End If
                                        Else
                                            Geb = G
                                            Bauliste = GB
                                        End If
                                    End If
                                End If
                            Next
                        End If

                    End If
            End Select
            If Bauliste IsNot Nothing Then
                Exit For
            End If
        Next

        If Bauliste IsNot Nothing Then

            Dim Beste As Integer = -1
            Dim Staerke As Integer = -1
            Dim Durchschnittskosten As Integer = 0
            For Each E In Bauliste
                Durchschnittskosten += E.Kosten
            Next
            Durchschnittskosten /= Bauliste.Length
            Dim Abweichung As Integer = Durchschnittskosten - BauPrioritaeten.DurchschnittlicheTruppenKosten
            If Abweichung < 0 Then Abweichung *= -1
            Abweichung += Durchschnittskosten / 4
            Dim DirectProz As Integer = 0
            If OwnUnits > 0 Then
                DirectProz = OwnDirectUnits / OwnUnits * 100
            End If
            If BauPrioritaeten.Direct <> PrioritaetsBau.Prioritaeten.Off Then
                For I = 0 To Bauliste.Length - 1
                    If Bauliste(I).MaximaleReichweite > 1 Then
                        If ObjektKI.CanMoveAfterBuilding(Bauliste(I), Geb.Rechteck.X, Geb.Rechteck.Y) Then
                            If Abweichung + BauPrioritaeten.DurchschnittlicheTruppenKosten >= Bauliste(I).Kosten Then
                                If Abweichung - BauPrioritaeten.DurchschnittlicheTruppenKosten <= Bauliste(I).Kosten Then
                                    Dim NeuStaerke As Int64 = CalculateDamage(Bauliste(I)) / (Bauliste(I).Kosten * KI.Spieler.Teurungsrate(Bauliste(I), Bauliste(I).X, Bauliste(I).Y))
                                    If Staerke < 0 Then
                                        Staerke = NeuStaerke
                                        Beste = I
                                    ElseIf NeuStaerke > Staerke Then
                                        Staerke = NeuStaerke
                                        Beste = I
                                    ElseIf NeuStaerke = Staerke And Zufallszahl(0, 2) = 0 Then
                                        Staerke = NeuStaerke
                                        Beste = I
                                    End If
                                End If
                            End If
                        End If
                    End If
                Next
                If Beste < 0 Then
                    For I = 0 To Bauliste.Length - 1
                        If ObjektKI.CanMoveAfterBuilding(Bauliste(I), Geb.Rechteck.X, Geb.Rechteck.Y) Then
                            If Abweichung + BauPrioritaeten.DurchschnittlicheTruppenKosten >= Bauliste(I).Kosten Then
                                If Abweichung - BauPrioritaeten.DurchschnittlicheTruppenKosten <= Bauliste(I).Kosten Then
                                    Dim NeuStaerke As Int64 = CalculateDamage(Bauliste(I)) / (Bauliste(I).Kosten * KI.Spieler.Teurungsrate(Bauliste(I), Bauliste(I).X, Bauliste(I).Y))
                                    If Staerke < 0 Then
                                        Staerke = NeuStaerke
                                        Beste = I
                                    ElseIf NeuStaerke > Staerke Then
                                        Staerke = NeuStaerke
                                        Beste = I
                                    ElseIf NeuStaerke = Staerke And Zufallszahl(0, 2) = 0 Then
                                        Staerke = NeuStaerke
                                        Beste = I
                                    End If
                                End If
                            End If
                        End If
                    Next
                End If
            ElseIf BauPrioritaeten.Indirect <> PrioritaetsBau.Prioritaeten.Off Then
                For I = 0 To Bauliste.Length - 1
                    If Bauliste(I).MaximaleReichweite = 1 Then
                        If ObjektKI.CanMoveAfterBuilding(Bauliste(I), Geb.Rechteck.X, Geb.Rechteck.Y) Then
                            If Abweichung + BauPrioritaeten.DurchschnittlicheTruppenKosten >= Bauliste(I).Kosten Then
                                If Abweichung - BauPrioritaeten.DurchschnittlicheTruppenKosten <= Bauliste(I).Kosten Then
                                    Dim NeuStaerke As Int64 = CalculateDamage(Bauliste(I)) / (Bauliste(I).Kosten * KI.Spieler.Teurungsrate(Bauliste(I), Bauliste(I).X, Bauliste(I).Y))
                                    If Staerke < 0 Then
                                        Staerke = NeuStaerke
                                        Beste = I
                                    ElseIf NeuStaerke > Staerke Then
                                        Staerke = NeuStaerke
                                        Beste = I
                                    ElseIf NeuStaerke = Staerke And Zufallszahl(0, 2) = 0 Then
                                        Staerke = NeuStaerke
                                        Beste = I
                                    End If
                                End If
                            End If
                        End If
                    End If
                Next
                If Beste < 0 Then
                    For I = 0 To Bauliste.Length - 1
                        If ObjektKI.CanMoveAfterBuilding(Bauliste(I), Geb.Rechteck.X, Geb.Rechteck.Y) Then
                            If Abweichung + BauPrioritaeten.DurchschnittlicheTruppenKosten >= Bauliste(I).Kosten Then
                                If Abweichung - BauPrioritaeten.DurchschnittlicheTruppenKosten <= Bauliste(I).Kosten Then
                                    Dim NeuStaerke As Int64 = CalculateDamage(Bauliste(I)) / (Bauliste(I).Kosten * KI.Spieler.Teurungsrate(Bauliste(I), Bauliste(I).X, Bauliste(I).Y))
                                    If Staerke < 0 Then
                                        Staerke = NeuStaerke
                                        Beste = I
                                    ElseIf NeuStaerke > Staerke Then
                                        Staerke = NeuStaerke
                                        Beste = I
                                    ElseIf NeuStaerke = Staerke And Zufallszahl(0, 2) = 0 Then
                                        Staerke = NeuStaerke
                                        Beste = I
                                    End If
                                End If
                            End If
                        End If
                    Next
                End If
            Else
                If OwnDirectUnits <= BauPrioritaeten.Direct / (BauPrioritaeten.Direct + BauPrioritaeten.Indirect) * 100 Then
                    'Nahwaffen bauen.
                    For I = 0 To Bauliste.Length - 1
                        If Bauliste(I).MaximaleReichweite = 1 Then
                            If ObjektKI.CanMoveAfterBuilding(Bauliste(I), Geb.Rechteck.X, Geb.Rechteck.Y) Then
                                If Abweichung + BauPrioritaeten.DurchschnittlicheTruppenKosten >= Bauliste(I).Kosten Then
                                    If Abweichung - BauPrioritaeten.DurchschnittlicheTruppenKosten <= Bauliste(I).Kosten Then
                                        Dim NeuStaerke As Int64 = CalculateDamage(Bauliste(I)) / (Bauliste(I).Kosten * KI.Spieler.Teurungsrate(Bauliste(I), Bauliste(I).X, Bauliste(I).Y))
                                        If Staerke < 0 Then
                                            Staerke = NeuStaerke
                                            Beste = I
                                        ElseIf NeuStaerke > Staerke Then
                                            Staerke = NeuStaerke
                                            Beste = I
                                        ElseIf NeuStaerke = Staerke And Zufallszahl(0, 2) = 0 Then
                                            Staerke = NeuStaerke
                                            Beste = I
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    Next
                    If Beste < 0 Then
                        For I = 0 To Bauliste.Length - 1
                            If ObjektKI.CanMoveAfterBuilding(Bauliste(I), Geb.Rechteck.X, Geb.Rechteck.Y) Then
                                If Abweichung + BauPrioritaeten.DurchschnittlicheTruppenKosten >= Bauliste(I).Kosten Then
                                    If Abweichung - BauPrioritaeten.DurchschnittlicheTruppenKosten <= Bauliste(I).Kosten Then
                                        Dim NeuStaerke As Int64 = CalculateDamage(Bauliste(I)) / (Bauliste(I).Kosten * KI.Spieler.Teurungsrate(Bauliste(I), Bauliste(I).X, Bauliste(I).Y))
                                        If Staerke < 0 Then
                                            Staerke = NeuStaerke
                                            Beste = I
                                        ElseIf NeuStaerke > Staerke Then
                                            Staerke = NeuStaerke
                                            Beste = I
                                        ElseIf NeuStaerke = Staerke And Zufallszahl(0, 2) = 0 Then
                                            Staerke = NeuStaerke
                                            Beste = I
                                        End If
                                    End If
                                End If
                            End If
                        Next
                    End If
                Else
                    'Fernwaffen bauen.
                    For I = 0 To Bauliste.Length - 1
                        If Bauliste(I).MaximaleReichweite > 1 Then
                            If ObjektKI.CanMoveAfterBuilding(Bauliste(I), Geb.Rechteck.X, Geb.Rechteck.Y) Then
                                If Abweichung + BauPrioritaeten.DurchschnittlicheTruppenKosten >= Bauliste(I).Kosten Then
                                    If Abweichung - BauPrioritaeten.DurchschnittlicheTruppenKosten <= Bauliste(I).Kosten Then
                                        Dim NeuStaerke As Int64 = CalculateDamage(Bauliste(I)) / (Bauliste(I).Kosten * KI.Spieler.Teurungsrate(Bauliste(I), Bauliste(I).X, Bauliste(I).Y))
                                        If Staerke < 0 Then
                                            Staerke = NeuStaerke
                                            Beste = I
                                        ElseIf NeuStaerke > Staerke Then
                                            Staerke = NeuStaerke
                                            Beste = I
                                        ElseIf NeuStaerke = Staerke And Zufallszahl(0, 2) = 0 Then
                                            Staerke = NeuStaerke
                                            Beste = I
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    Next
                    If Beste < 0 Then
                        For I = 0 To Bauliste.Length - 1
                            If ObjektKI.CanMoveAfterBuilding(Bauliste(I), Geb.Rechteck.X, Geb.Rechteck.Y) Then
                                If Abweichung + BauPrioritaeten.DurchschnittlicheTruppenKosten >= Bauliste(I).Kosten Then
                                    If Abweichung - BauPrioritaeten.DurchschnittlicheTruppenKosten <= Bauliste(I).Kosten Then
                                        Dim NeuStaerke As Int64 = CalculateDamage(Bauliste(I)) / (Bauliste(I).Kosten * KI.Spieler.Teurungsrate(Bauliste(I), Bauliste(I).X, Bauliste(I).Y))
                                        If Staerke < 0 Then
                                            Staerke = NeuStaerke
                                            Beste = I
                                        ElseIf NeuStaerke > Staerke Then
                                            Staerke = NeuStaerke
                                            Beste = I
                                        ElseIf NeuStaerke = Staerke And Zufallszahl(0, 2) = 0 Then
                                            Staerke = NeuStaerke
                                            Beste = I
                                        End If
                                    End If
                                End If
                            End If
                        Next
                    End If
                End If
            End If
            If Beste >= 0 Then
                Ausgabe = Bauliste(Beste).Kosten * KI.Spieler.Teurungsrate(Bauliste(Beste), Bauliste(Beste).X, Bauliste(Beste).Y)
                ProduceUnit(Geb, Bauliste(Beste))
                Return Ausgabe
            Else
                'So trotzdem was bauen
            End If
        End If
        Return Ausgabe
    End Function
#End Region

#Region "Count Units and Buildings and Stuff like that!"
    ''' <summary>
    ''' Zaehlt die Lufteinheiten, welche Angreifen koennen.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountEnemyAirUnits() As Integer
        Dim AirTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                        If Not E Is Nothing Then
                            If E.IsFlyingUnit Then
                                If E.CanAttack Then
                                    If E.GetSpieler.Team <> Objektverwalter.Spielfeld.CurrentAI.Spieler.Team Then
                                        AirTroops += 1
                                    End If
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return AirTroops
    End Function
    ''' <summary>
    ''' Zaehlt die Fernwaffen der Gegner.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountIndirectEnemys() As Integer
        Dim IndirectTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                        If Not E Is Nothing Then
                            If E.IsFlyingUnit Then
                                If E.MaximaleReichweite > 1 Then
                                    If E.GetSpieler.Team <> Objektverwalter.Spielfeld.CurrentAI.Spieler.Team Then
                                        IndirectTroops += 1
                                    End If
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return IndirectTroops
    End Function
    ''' <summary>
    ''' Zaehlt die Direktwaffen der Gegner.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountDirectEnemys() As Integer
        Dim IndirectTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                        If Not E Is Nothing Then
                            If E.IsFlyingUnit Then
                                If E.MinimaleReichweite = 1 Or E.Waffe1 <> "Keine" Then
                                    If E.GetSpieler.Team <> Objektverwalter.Spielfeld.CurrentAI.Spieler.Team Then
                                        IndirectTroops += 1
                                    End If
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return IndirectTroops
    End Function
    ''' <summary>
    ''' Zaehlt die Fernwaffen.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountIndirectUnits() As Integer
        Dim IndirectTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                        If Not E Is Nothing Then
                            If E.MaximaleReichweite > 1 Then
                                If E.Spieler <> Objektverwalter.Spielfeld.CurrentAI.Spieler.Spieler Then
                                    IndirectTroops += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return IndirectTroops
    End Function
    ''' <summary>
    ''' Zaehlt die Direktwaffen.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountDirectUnits() As Integer
        Dim IndirectTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                        If Not E Is Nothing Then
                            If E.MinimaleReichweite = 1 Or E.Waffe1 <> "Keine" Then
                                If E.Spieler = Objektverwalter.Spielfeld.CurrentAI.Spieler.Spieler Then
                                    IndirectTroops += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return IndirectTroops
    End Function
    ''' <summary>
    ''' Wie viele Neutrale Besetzungen es noch gibt!
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountNeutralBuildings() As Integer
        Dim IndirectTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X, Y, I).Gebaeude
                        If Not G Is Nothing Then
                            If G.Spieler = 0 Then
                                If G.Besetzung > 0 Then
                                    IndirectTroops += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return IndirectTroops
    End Function
    ''' <summary>
    ''' Wie viele feindliche Besetzungen es noch gibt!
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountEnemyBuildings() As Integer
        Dim IndirectTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X, Y, I).Gebaeude
                        If Not G Is Nothing Then
                            If G.GetSpieler.Team <> Objektverwalter.Spielfeld.CurrentAI.Spieler.Team Then
                                If G.Besetzung > 0 Then
                                    IndirectTroops += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return IndirectTroops
    End Function
    ''' <summary>
    ''' Zaehlt die Zahl der Einheiten die Bomber angreifen koennen!
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountAntiAirUnits() As Integer
        Dim AirTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                        If Not E Is Nothing Then
                            If E.Spieler = Objektverwalter.Spielfeld.CurrentAI.Spieler.Spieler Then
                                If E.IsAttackable(New EinheitBomber(0, X, Y, False), False, False) Then
                                    AirTroops += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return AirTroops
    End Function
    ''' <summary>
    ''' Zaehlt die Zahl der feindlichen Einheiten die Bomber angreifen koennen!
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountEnemyAntiAirUnits() As Integer
        Dim AirTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                        If Not E Is Nothing Then
                            If E.GetSpieler.Team <> Objektverwalter.Spielfeld.CurrentAI.Spieler.Team Then
                                If E.IsAttackable(New EinheitBomber(0, X, Y, False), False, False) Then
                                    AirTroops += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return AirTroops
    End Function
    ''' <summary>
    ''' Zaehlt die Zahl der Bodeneinheiten + Amphibientruppen
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountGroundUnits() As Integer
        Dim AirTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                        If Not E Is Nothing Then
                            If E.Spieler = Objektverwalter.Spielfeld.CurrentAI.Spieler.Spieler Then
                                If E.IsGroundUnit Then
                                    AirTroops += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return AirTroops
    End Function
    ''' <summary>
    ''' Zaehlt die Zahl der Seeeinheiten
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountSeaUnits() As Integer
        Dim AirTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                        If Not E Is Nothing Then
                            If E.Spieler = Objektverwalter.Spielfeld.CurrentAI.Spieler.Spieler Then
                                If E.IsSeaUnit Then
                                    AirTroops += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return AirTroops
    End Function
    ''' <summary>
    ''' Zaehlt die Zahl der Lufteinheiten
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountAirUnits() As Integer
        Dim AirTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                        If Not E Is Nothing Then
                            If E.Spieler = Objektverwalter.Spielfeld.CurrentAI.Spieler.Spieler Then
                                If E.IsFlyingUnit Then
                                    AirTroops += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return AirTroops
    End Function
    ''' <summary>
    ''' Zaehlt die Zahl der feindlichen Bodeneinheiten + Amphibientruppen
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountEnemyGroundUnits() As Integer
        Dim AirTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                        If Not E Is Nothing Then
                            If E.GetSpieler.Team = Objektverwalter.Spielfeld.CurrentAI.Spieler.Team Then
                                If E.IsGroundUnit Then
                                    AirTroops += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return AirTroops
    End Function
    ''' <summary>
    ''' Zaehlt die Zahl der feindlichen Seeeinheiten
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountEnemySeaUnits() As Integer
        Dim AirTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                        If Not E Is Nothing Then
                            If E.GetSpieler.Team = Objektverwalter.Spielfeld.CurrentAI.Spieler.Team Then
                                If E.IsSeaUnit Then
                                    If E.CanAttack Then
                                        AirTroops += 1
                                    End If
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return AirTroops
    End Function
    ''' <summary>
    ''' Zaehlt die Zahl der feindlichen Einheiten
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountEnemyUnits() As Integer
        Dim AirTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                        If Not E Is Nothing Then
                            If E.GetSpieler.Team = Objektverwalter.Spielfeld.CurrentAI.Spieler.Team Then
                                AirTroops += 1
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return AirTroops
    End Function
    ''' <summary>
    ''' Zaehlt die Zahl der feindlichen Helikopter
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountEnemyCopters() As Integer
        Dim AirTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                        If Not E Is Nothing Then
                            If E.GetSpieler.Team = Objektverwalter.Spielfeld.CurrentAI.Spieler.Team Then
                                If E.Bewegungsart = MovementSorts.Helikopter.ToString Then
                                    If Not E.HasNoWeapons Then
                                        AirTroops += 1
                                    End If
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return AirTroops
    End Function
    ''' <summary>
    ''' Zaehlt die eigenen Truppen
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountOwnUnits() As Integer
        Dim AirTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                        If Not E Is Nothing Then
                            If E.Spieler = Objektverwalter.Spielfeld.CurrentAI.Spieler.Spieler Then
                                AirTroops += 1
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return AirTroops
    End Function
    ''' <summary>
    ''' Wie viele Basen haben wir.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountOwnBases() As Integer
        Dim IndirectTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X, Y, I).Gebaeude
                        If Not G Is Nothing Then
                            If G.GetSpieler.Team <> Objektverwalter.Spielfeld.CurrentAI.Spieler.Team Then
                                If TypeOf G Is GebaeudeBasis Then
                                    IndirectTroops += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return IndirectTroops
    End Function
    ''' <summary>
    ''' Wie viele Flughafen haben wir.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountOwnAirports() As Integer
        Dim IndirectTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X, Y, I).Gebaeude
                        If Not G Is Nothing Then
                            If G.GetSpieler.Team <> Objektverwalter.Spielfeld.CurrentAI.Spieler.Team Then
                                If TypeOf G Is GebaeudeFlughafen Then
                                    IndirectTroops += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return IndirectTroops
    End Function
    ''' <summary>
    ''' Wie viele Hafen haben wir.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountOwnPorts() As Integer
        Dim IndirectTroops As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X, Y, I).Gebaeude
                        If Not G Is Nothing Then
                            If G.GetSpieler.Team <> Objektverwalter.Spielfeld.CurrentAI.Spieler.Team Then
                                If TypeOf G Is GebaeudeHafen Then
                                    IndirectTroops += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return IndirectTroops
    End Function
    ''' <summary>
    ''' Gibt die Anzahl der Infanteristen die dieser Spieler kontrolliert zurueck
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountInfanteristen() As Integer
        Dim Infanteristen As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                        If Not E Is Nothing Then
                            If E.Spieler = Objektverwalter.Spielfeld.CurrentAI.Spieler.Spieler Then
                                If E.KannBesetzen = True Then
                                    If E.Leben > 0 Then
                                        Infanteristen += 1
                                    End If
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return Infanteristen
    End Function
    ''' <summary>
    ''' Gibt die Anzahl der Einheiten von einem bestimmten Typ zurueck.
    ''' </summary>
    ''' <param name="EinheitenID"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountAnyUnit(ByVal EinheitenID As String) As Integer
        Dim Units As Integer = 0
        Dim Schlacht As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht Then Schlacht += 1
        For I = 0 To Schlacht
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                        If Not E Is Nothing Then
                            If E.Spieler = Objektverwalter.Spielfeld.CurrentAI.Spieler.Spieler Then
                                If E.Leben > 0 Then
                                    If EinheitenID = E.EinheitenID Then
                                        Units += 1
                                    End If
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return Units
    End Function
    ''' <summary>
    ''' Wie viel Geld jeder Spieler bekommt
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CountEnemyBuildingsEachPlayer() As List(Of Integer)
        Dim L As New List(Of Integer)
        For Each S In Objektverwalter.Spielfeld.Spieler
            If S.Spieler > 0 Then
                If S.Team <> KI.Spieler.Team Then
                    L.Add(S.GetGebaeude(ObjektSpieler.Gebaeudesuche.Fonds))
                End If
            End If
        Next
        Return L
    End Function
    ''' <summary>
    ''' Vergleicht unsere Einnahmen mit denen des besten Spielers
    ''' 100%=Gleichstand an Einnahmen!
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function ProzentualeGebaeudeVerteilung() As Single
        Dim EigeneGGebaeude As Integer = 0
        For Each S In Objektverwalter.Spielfeld.Spieler
            If S.Team = KI.Spieler.Team Then
                EigeneGGebaeude += S.GetGebaeude(ObjektSpieler.Gebaeudesuche.Fonds) * S.FondsproStadt
            End If
        Next
        Dim T As New List(Of String)
        Dim F As New List(Of Integer)
        For Each S In Objektverwalter.Spielfeld.Spieler
            If S.Spieler > 0 Then
                If S.Team <> KI.Spieler.Team Then
                    If T.Contains(S.Team) Then
                        Dim I As Integer = T.LastIndexOf(S.Team)
                        F(I) += S.GetGebaeude(ObjektSpieler.Gebaeudesuche.Fonds) * S.FondsproStadt
                    Else
                        F.Add(S.GetGebaeude(ObjektSpieler.Gebaeudesuche.Fonds) * S.FondsproStadt)
                        T.Add(S.Team)
                    End If
                End If
            End If
        Next
        F.Sort()
        Return EigeneGGebaeude / F(F.Count - 1) * 100
    End Function
    ''' <summary>
    ''' In welcher Reihenfolge wir Boden, See oder Luftwaffen bauen
    ''' </summary>
    ''' <remarks></remarks>
    Private Shared Sub GenerateBauWichtigkeit()
        BauWichtigKeit = New List(Of TruppenSorten)
        If BauPrioritaeten.Air < BauPrioritaeten.Sea Then
            If BauPrioritaeten.Land < BauPrioritaeten.Sea Then
                BauWichtigKeit.Add(TruppenSorten.Air)
                BauWichtigKeit.Add(TruppenSorten.Sea)
                BauWichtigKeit.Add(TruppenSorten.Ground)
            Else
                BauWichtigKeit.Add(TruppenSorten.Air)
                BauWichtigKeit.Add(TruppenSorten.Ground)
                BauWichtigKeit.Add(TruppenSorten.Sea)
            End If
        ElseIf BauPrioritaeten.Air <= BauPrioritaeten.Land Then
            If BauPrioritaeten.Land < BauPrioritaeten.Sea Then
                BauWichtigKeit.Add(TruppenSorten.Sea)
                BauWichtigKeit.Add(TruppenSorten.Ground)
                BauWichtigKeit.Add(TruppenSorten.Air)
            Else
                BauWichtigKeit.Add(TruppenSorten.Ground)
                BauWichtigKeit.Add(TruppenSorten.Sea)
                BauWichtigKeit.Add(TruppenSorten.Air)
            End If
        Else
            If BauPrioritaeten.Land < BauPrioritaeten.Sea Then
                BauWichtigKeit.Add(TruppenSorten.Air)
                BauWichtigKeit.Add(TruppenSorten.Sea)
                BauWichtigKeit.Add(TruppenSorten.Ground)
            Else
                BauWichtigKeit.Add(TruppenSorten.Air)
                BauWichtigKeit.Add(TruppenSorten.Ground)
                BauWichtigKeit.Add(TruppenSorten.Sea)
            End If
        End If

    End Sub
#End Region
#Region "Checking Stuff functions giving back true or false or integers. This functions simply rock!"
    ''' <summary>
    ''' Lohnt es sich ueberhaupt Landeboote zu bauen?
    ''' </summary>
    ''' <param name="Gebaeude"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function IsTransporterBauSinnvoll(ByVal Gebaeude() As ObjektGebaeude) As Boolean
        For Each Unit In Objektverwalter.Spielfeld.Einheiten
            If Unit IsNot Nothing Then
                If Unit.Spieler = KI.Spieler.Spieler Then
                    If Unit.CanAttack Then
                        If Not Unit.IsSeaUnit Then
                            If Not Unit.IsFlyingUnit Then
                                Dim WSS As New Wegsuchsystem(Unit, , False, Wegsuchsystem.SuchartenEinheiten.AlleEinheitenIgnorieren)
                                If WSS.Wegsuchen(True, Unit.KannBesetzen) < 0 Then
                                    Return True
                                End If
                            End If
                        End If
                    End If
                End If
            End If
        Next
        Return False
    End Function
    ''' <summary>
    ''' Entfernt einfach mal die Gebaeude die wir nicht brauchen
    ''' </summary>
    ''' <param name="Gebaeude"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function TrimGebaeude(ByVal Gebaeude As ObjektGebaeude()) As ObjektGebaeude()
        Dim G2 As New Stack(Of ObjektGebaeude)
        For I = 0 To Gebaeude.Length - 1
            If Gebaeude(I).GetBaulisteThisPlayer.Length > 0 Then
                G2.Push(Gebaeude(I))
            End If
        Next
        Gebaeude = G2.ToArray
        Return Gebaeude
    End Function
    Private Shared Function SortGebaeude(ByVal G As ObjektGebaeude(), ByVal Spieler As ObjektSpieler) As ObjektGebaeude()
        Dim Entfernungen(G.Length - 1) As Integer
        For I = 0 To G.Length - 1
            Dim E As ObjektEinheit = Nothing
            If TypeOf G(I) Is GebaeudeBasis Then
                E = New EinheitJagdpanzer(Spieler.Spieler, G(I).Rechteck.X, G(I).Rechteck.Y, False)
            ElseIf TypeOf G(I) Is GebaeudeFlughafen Then
                E = New EinheitTarnkappenbomber(Spieler.Spieler, G(I).Rechteck.X, G(I).Rechteck.Y, False)
            ElseIf TypeOf G(I) Is GebaeudeHafen Then
                E = New EinheitKreuzer(Spieler.Spieler, G(I).Rechteck.X, G(I).Rechteck.Y, False)
            ElseIf TypeOf G(I) Is GebaeudeLabor Then
                E = New EinheitMech(Spieler.Spieler, G(I).Rechteck.X, G(I).Rechteck.Y, False)
            ElseIf TypeOf G(I) Is GebaeudeStadt And G(I).GetBaulisteThisPlayer.Length > 0 Then
                E = New EinheitJagdpanzer(Spieler.Spieler, G(I).Rechteck.X, G(I).Rechteck.Y, False)
            End If
            If E Is Nothing Then
                Entfernungen(I) = -1
            Else
                Dim WSS As New Wegsuchsystem(E, E.X, E.Y, Objektverwalter.Spielfeld.MomentaneSchlacht, -1, False)
                Entfernungen(I) = WSS.Wegsuchen(True, False)
            End If
        Next
        Dim G2(G.Length - 1) As ObjektGebaeude
        For I = 0 To G2.Length - 1
            Dim MaxMovementRange As Integer = Objektverwalter.Spielfeld.Breite * Objektverwalter.Spielfeld.Hoehe
            Dim GebaeudeStelle As Integer = 0
            For I2 = 0 To G.Length - I - 1
                If Entfernungen(I2) < MaxMovementRange And Entfernungen(I2) >= 0 Then
                    GebaeudeStelle = I2
                    MaxMovementRange = Entfernungen(I2)
                ElseIf Entfernungen(I2) = MaxMovementRange And Entfernungen(I2) >= 0 And Zufallszahl(0, 1) = 0 Then
                    GebaeudeStelle = I2
                    MaxMovementRange = Entfernungen(I2)
                End If
            Next
            G2(I) = G(GebaeudeStelle)
            Entfernungen(GebaeudeStelle) = Entfernungen(Entfernungen.Length - I - 1)
            G(GebaeudeStelle) = G(G.Length - I - 1)
        Next
        Return G2
    End Function
    ''' <summary>
    ''' Gibt zurueck ob das Feld leer ist.
    ''' </summary>
    ''' <param name="X"></param>
    ''' <param name="Y"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function IsFeldLeer(ByVal X As Integer, ByVal Y As Integer) As Boolean
        If Not Objektverwalter.Spielfeld.Landschaften(X, Y, ObjektKI.Schlachtfeld).Hidden Then
            If IsNothing(Objektverwalter.Spielfeld.Einheiten(X, Y, ObjektKI.Schlachtfeld)) Then
                Return True
            ElseIf Objektverwalter.Spielfeld.Einheiten(X, Y, ObjektKI.Schlachtfeld).Leben <= 0 Then
                Return True
            Else
                Return False
            End If
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Gibt zurueck welche Infanteristen von diesem Gebaeude gebaut werden koennen.
    ''' </summary>
    ''' <param name="BauGebaeude"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function GetBuildInfis(ByVal BauGebaeude As ObjektGebaeude, ByVal Prueffonds As Integer) As String()
        Dim Infis As New Stack(Of String)
        Dim BListe As String() = BauGebaeude.GetBaulisteThisPlayer
        For I = 0 To BListe.Length - 1
            If ObjektLadeklasse.NewEinheit(BListe(I), 1, -1, -1).KannBesetzen = True Then
                If BauGebaeude.CanBuildUnit(BListe(I), Prueffonds) = True Then
                    Infis.Push(BListe(I))
                End If
            End If
        Next
        Return Infis.ToArray
    End Function
    ''' <summary>
    ''' Wie viele Truppen brauchen neuen Treibstoff!
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function GetNeededRation() As Boolean
        Dim RationsTruppen As Integer = 0
        For Each Unit In Objektverwalter.Spielfeld.Einheiten
            If Unit IsNot Nothing Then
                If Unit.Spieler = KI.Spieler.Spieler Then
                    If Unit.Treibstoff / Unit.SpritMax <= KI.MinimalerTreibstoff Then
                        RationsTruppen += 1
                    ElseIf Unit.Munition / Unit.MunitionMax <= KI.MinimaleMunition Then
                        RationsTruppen += 1
                    End If
                End If
            End If
        Next
        Return RationsTruppen
    End Function
    ''' <summary>
    ''' Brauchen wir was gegen Luftwaffe (T-Heli's und T-Flugzeuge zaehlen nicht!) 
    ''' </summary>
    ''' <param name="AntiAirUnits"></param>
    ''' <param name="EnemyAirUnits"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function AntiAirBau(ByVal AntiAirUnits As Integer, ByVal EnemyAirUnits As Integer) As Boolean
        If EnemyAirUnits > 0 Then 'Sonst brauchen wir das ja wohl kaum!!!
            If AntiAirUnits <= 0 Then
                Return True
            ElseIf EnemyAirUnits / AntiAirUnits >= 0.5# Then 'Diw Teiler sind noch Variabel
                Return True
            End If
        End If
        Return False
    End Function
    ''' <summary>
    ''' Wie lange ein Jaeger braucht zur naechsten Lufteinheit
    ''' </summary>
    ''' <param name="G"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function GetAirDistance(ByVal G As ObjektGebaeude, ByVal Truppensorte As TruppenSorten) As Integer
        Dim WSS As Wegsuchsystem
        Select Case Truppensorte
            Case TruppenSorten.Sea
                WSS = New Wegsuchsystem(New EinheitKreuzer(G.Spieler, G.Rechteck.X, G.Rechteck.Y, False), G.Rechteck.X, G.Rechteck.Y, 0, False, Wegsuchsystem.SuchartenEinheiten.AlleEinheitenIgnorieren)
            Case TruppenSorten.Air
                WSS = New Wegsuchsystem(New EinheitJaeger(G.Spieler, G.Rechteck.X, G.Rechteck.Y, False), G.Rechteck.X, G.Rechteck.Y, 0, , False, Wegsuchsystem.SuchartenEinheiten.AlleEinheitenIgnorieren)
            Case TruppenSorten.Ground
                WSS = New Wegsuchsystem(New EinheitFlak(G.Spieler, G.Rechteck.X, G.Rechteck.Y, False), G.Rechteck.X, G.Rechteck.Y, 0, , False, Wegsuchsystem.SuchartenEinheiten.AlleEinheitenIgnorieren)
            Case Else
                WSS = New Wegsuchsystem(New EinheitJaeger(G.Spieler, G.Rechteck.X, G.Rechteck.Y, False), G.Rechteck.X, G.Rechteck.Y, 0, , False, Wegsuchsystem.SuchartenEinheiten.AlleEinheitenIgnorieren)
        End Select
        Return WSS.Wegsuchen(True, False)
    End Function
    ''' <summary>
    ''' Berechnet wie viel Schaden wir allen Feinden zu fuegen wuerden!
    ''' </summary>
    ''' <param name="Attacker"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function CalculateDamage(ByVal Attacker As ObjektEinheit) As Int64
        Dim Staerke As Int64 = 0
        For Each Unit In Objektverwalter.Spielfeld.Einheiten
            If Unit IsNot Nothing Then
                If Attacker.IsAttackable(Unit, False, False) Then
                    If Unit.GetSpieler.Team <> Objektverwalter.Spielfeld.CurrentAI.Spieler.Team Then
                        If Not Unit.IsFlyingUnit Then
                            Staerke += GegnerVerluste(Attacker, Attacker.X, Attacker.Y, Unit, Unit.X, Unit.Y)
                        End If
                    End If
                End If
            End If
        Next
        Return Staerke
    End Function
    ''' <summary>
    ''' Wie viel Schaden wir bei einem Gegner ausrichten wuerden!
    ''' </summary>
    ''' <param name="Angreifer"></param>
    ''' <param name="AX"></param>
    ''' <param name="AY"></param>
    ''' <param name="Verteidiger"></param>
    ''' <param name="VX"></param>
    ''' <param name="VY"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function GegnerVerluste(ByVal Angreifer As ObjektEinheit, ByVal AX As Integer, ByVal AY As Integer, ByVal Verteidiger As ObjektEinheit, ByVal VX As Integer, ByVal VY As Integer) As Integer
        Dim ATKLeben As Single = Angreifer.Leben
        Dim DefLeben As Single = Verteidiger.Leben
        Dim GegenSchaden As Integer() = Angreifer.GetDamage(Verteidiger, False, False)
        If GegenSchaden(0) < 0 Then GegenSchaden(1) = 0
        DefLeben -= GegenSchaden(0) * Angreifer.Leben / 100
        If DefLeben < 0 Then DefLeben = 0
        If Not (GegenSchaden(1) = 2 And Angreifer.MaximaleReichweite > 1) Then
            GegenSchaden = Verteidiger.GetDamage(Angreifer, False, False)
            ATKLeben -= GegenSchaden(0) * DefLeben / 100
            If ATKLeben < 0 Then ATKLeben = 0
        End If
        Dim KVerteidiger As Integer = (Verteidiger.Kosten * Verteidiger.GetSpieler.Teurungsrate(Verteidiger, VX, VY)) * ((Verteidiger.Leben - DefLeben) / 100)
        Dim KAngreifer As Integer = (Angreifer.Kosten * Angreifer.GetSpieler.Teurungsrate(Angreifer, AX, AY)) * ((Angreifer.Leben - ATKLeben) / 100)
        Return KVerteidiger * 2 - KAngreifer
    End Function
    ''' <summary>
    ''' Berechnet wie viel Schaden wir allen fliegenden Feinden zu fuegen wuerden!
    ''' </summary>
    ''' <param name="Attacker"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function GetAntiAirDamage(ByVal Attacker As ObjektEinheit) As Integer
        Dim Staerke As Integer = 0
        For Each Unit In Objektverwalter.Spielfeld.Einheiten
            If Unit IsNot Nothing Then
                If Attacker.IsAttackable(Unit, False, False) Then
                    If Unit.IsFlyingUnit Then
                        If KI IsNot Nothing Then
                            If Unit.GetSpieler.Team <> KI.Spieler.Team Then
                                Staerke += GegnerVerluste(Attacker, Attacker.X, Attacker.Y, Unit, Unit.X, Unit.Y)
                            End If
                        ElseIf Unit.GetSpieler.Team <> Objektverwalter.Spielfeld.AktuellerSpieler.Team Then
                            Staerke += GegnerVerluste(Attacker, Attacker.X, Attacker.Y, Unit, Unit.X, Unit.Y)
                        End If
                    End If
                End If
            End If
        Next
        Return Staerke
    End Function
#End Region
End Class